Class và OOP trong TypeScript
Bài 11 – Class, constructor, thuộc tính, phương thức và OOP trong TypeScript theo cách đơn giản, trực quan và tiêu chuẩn.
Class và Lập trình hướng đối tượng trong TypeScript
TypeScript bổ sung typing vào mô hình OOP của JavaScript, giúp class rõ ràng, an toàn và mạnh mẽ hơn. Đây là nền tảng quan trọng khi xây dựng mô hình dữ liệu, xử lý nghiệp vụ hoặc cấu trúc ứng dụng lớn.
2. Nội dung chính
- Class và cách khai báo class
- Constructor và thuộc tính
- Access modifiers: public, private, protected
- Kế thừa (extends) và ghi đè (override)
- Getter – Setter
- Static property và static method
- Ứng dụng OOP trong dự án thực tế
3. Ví dụ chi tiết
3.1. Class cơ bản
class User {
public id: number;
public name: string;
private password: string;
constructor(id: number, name: string, password: string) {
this.id = id;
this.name = name;
this.password = password;
}
greet() {
console.log(`Hello, ${this.name}`);
}
private encryptPassword() {
return `***${this.password}***`;
}
// Public method để truy cập private method
getEncryptedPassword() {
return this.encryptPassword();
}
}
const u = new User(1, "Alice", "123456");
u.greet(); // Hello, Alice
console.log(u.name); // Alice
// u.password; // ❌ Error: private property
3.2. Kế thừa class
class Admin extends User {
public role: string;
constructor(id: number, name: string, password: string, role: string) {
super(id, name, password);
this.role = role;
}
// Override method
greet() {
console.log(`Admin ${this.name} with role: ${this.role}`);
}
// Thêm method mới
manageSystem() {
console.log(`${this.name} is managing the system`);
}
}
const admin = new Admin(2, "Bob", "pass123", "superadmin");
admin.greet(); // Admin Bob with role: superadmin
admin.manageSystem(); // Bob is managing the system
3.3. Getter – Setter
class Product {
constructor(private _price: number) {}
get price() {
return this._price;
}
set price(value: number) {
if (value < 0) throw new Error("Invalid price");
this._price = value;
}
get formattedPrice() {
return `$${this._price.toFixed(2)}`;
}
}
const p = new Product(100);
console.log(p.price); // 100
console.log(p.formattedPrice); // $100.00
p.price = 25; // ✅ Valid
// p.price = -10; // ❌ Error: Invalid price
3.4. Static property – method
class MathUtil {
static PI = 3.14159;
static E = 2.71828;
static sum(a: number, b: number): number {
return a + b;
}
static circleArea(radius: number): number {
return this.PI * radius * radius;
}
static randomBetween(min: number, max: number): number {
return Math.random() * (max - min) + min;
}
}
console.log(MathUtil.PI); // 3.14159
console.log(MathUtil.sum(3, 4)); // 7
console.log(MathUtil.circleArea(5)); // 78.53975
console.log(MathUtil.randomBetween(1, 10)); // Random number
3. Kiến thức trọng tâm
3.1. Access modifiers giúp kiểm soát quyền truy cập
| Modifier | Truy cập trong class | Truy cập trong subclass | Truy cập từ bên ngoài |
|---|---|---|---|
public | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ❌ |
private | ✅ | ❌ | ❌ |
💡 GHI NHỚ: Mặc định là
publicnếu không chỉ định
3.2. Kế thừa và ghi đè giúp tái sử dụng và mở rộng hành vi
- Hữu ích khi xây dựng mô hình: User → Admin, Product → DigitalProduct
- Ghi đè (override) cho phép thay đổi hành vi của parent class
- super() gọi constructor của parent class
- super.method() gọi method của parent class
3.3. Static dùng cho logic “thuộc về class”, không thuộc về instance
- Hàm tiện ích:
MathUtil.sum(),DateUtil.format() - Hằng số:
MathUtil.PI,AppConfig.API_URL - Factory methods:
User.createAdmin(),Product.createDefault() - Không cần tạo instance để sử dụng
4. Bài tập thực hành
Bài 1: Tạo class Customer
class Customer {
constructor(
public id: number,
public name: string,
public email: string
) {}
greet() {
console.log(`Hello ${this.name}, your email is ${this.email}`);
}
updateEmail(newEmail: string) {
this.email = newEmail;
}
}
const customer = new Customer(1, "John Doe", "john@example.com");
customer.greet(); // Hello John Doe, your email is john@example.com
Bài 2: Tạo class VIPCustomer kế thừa Customer
class VIPCustomer extends Customer {
constructor(
id: number,
name: string,
email: string,
public level: "bronze" | "silver" | "gold" | "platinum",
private discount: number = 0
) {
super(id, name, email);
}
getDiscount() {
return this.discount;
}
override greet() {
console.log(`VIP Customer ${this.name} - Level: ${this.level}`);
}
calculatePrice(originalPrice: number) {
return originalPrice * (1 - this.discount);
}
}
const vip = new VIPCustomer(2, "Jane Smith", "jane@example.com", "gold", 0.15);
vip.greet(); // VIP Customer Jane Smith - Level: gold
console.log(vip.calculatePrice(100)); // 85 (15% discount)
Bài 3: Tạo class Circle với static methods
class Circle {
static PI = 3.14159265359;
constructor(public radius: number) {}
getArea(): number {
return Circle.PI * this.radius * this.radius;
}
getCircumference(): number {
return 2 * Circle.PI * this.radius;
}
static areaFromRadius(radius: number): number {
return this.PI * radius * radius;
}
static circumferenceFromRadius(radius: number): number {
return 2 * this.PI * radius;
}
}
const circle = new Circle(5);
console.log(circle.getArea()); // 78.53981633975
console.log(circle.getCircumference()); // 31.4159265359
console.log(Circle.areaFromRadius(10)); // 314.159265359
console.log(Circle.circumferenceFromRadius(10)); // 62.8318530718
5. Sai lầm thường gặp
- Không sử dụng access modifiers: Làm code dễ bị thay đổi từ bên ngoài
- Dùng static cho mọi thứ: Static không phù hợp cho state của object
- Kế thừa quá nhiều cấp: Làm code khó hiểu và bảo trì
- Không hiểu về
this: Gây lỗi khi method bị gọi trong context khác - Quên gọi
super(): Gây lỗi khi kế thừa class
⚠️ GHI NHỚ: Composition thường tốt hơn inheritance
6. Kết luận
Class trong TypeScript mạnh hơn JavaScript nhờ typing, access modifiers và khả năng mở rộng rõ ràng. Đây là nền tảng quan trọng khi bạn xây dựng mô hình dữ liệu và nghiệp vụ trong dự án lớn.
🔑 GHI NHỚ QUAN TRỌNG:
- Sử dụng access modifiers để bảo vệ dữ liệu
- Kế thừa đúng cách với extends và super
- Getter/Setter cho validation và encapsulation
- Static cho utility functions và constants
- Hiểu về this binding để tránh lỗi runtime