TypeScript bổ sung cho lớp JavaScript các công cụ kiểm soát truy cập, lớp trừu tượng và cài đặt interface, giúp tổ chức mã hướng đối tượng chặt chẽ.
Bạn sẽ học được
- Khai báo lớp có kiểu thuộc tính
- Dùng public, private, protected, readonly và #private
- Kế thừa, lớp trừu tượng, implements
- Biết khi nào nên dùng lớp, khi nào dùng hàm
Thuật ngữ cần biết
- Access modifier
- Từ khóa kiểm soát truy cập: public, private, protected.
- Parameter property
- Khai báo thuộc tính ngay trong tham số constructor.
- Abstract class
- Lớp không tạo đối tượng trực tiếp, chứa phương thức trừu tượng.
- implements
- Lớp cam kết cài đặt một interface.
Khái niệm và lý thuyết
Lớp gói dữ liệu (thuộc tính) và hành vi (phương thức). Bốn nguyên lý OOP: đóng gói, kế thừa, đa hình, trừu tượng. TS hỗ trợ đủ cả bốn ở mức kiểu.
Lưu ý private của TS chỉ kiểm tra lúc biên dịch; còn #ten là private thật của JavaScript, ẩn cả khi chạy. Trong mã mới nên dùng # cho dữ liệu cần bảo vệ thực sự.
Lớp cơ bản
class TaiKhoan {
#soDu = 0; // private thật (runtime)
constructor(public readonly chuTK: string) {}
napTien(soTien: number): void {
if (soTien <= 0) throw new Error("Số tiền không hợp lệ");
this.#soDu += soTien;
}
get soDu(): number { return this.#soDu; }
}
const tk = new TaiKhoan("An");
tk.napTien(500_000);
console.log(tk.soDu);Kế thừa và trừu tượng
abstract class Hinh {
abstract dienTich(): number;
moTa() { return `Diện tích: ${this.dienTich().toFixed(2)}`; }
}
class Tron extends Hinh {
constructor(private r: number) { super(); }
dienTich() { return Math.PI * this.r ** 2; }
}
class ChuNhat extends Hinh {
constructor(private d: number, private r: number) { super(); }
override dienTich() { return this.d * this.r; }
}
const ds: Hinh[] = [new Tron(1), new ChuNhat(2, 3)];
ds.forEach(h => console.log(h.moTa())); // đa hìnhimplements interface
interface LuuTru<T> {
luu(khoa: string, gt: T): void;
doc(khoa: string): T | undefined;
}
class BoNhoTam<T> implements LuuTru<T> {
private kho = new Map<string, T>();
luu(k: string, gt: T) { this.kho.set(k, gt); }
doc(k: string) { return this.kho.get(k); }
}Mẹo hay
Bật noImplicitOverride để bắt buộc ghi override khi ghi đè phương thức lớp cha, tránh vô tình ghi đè hoặc gõ sai tên.
Lưu ý
Đừng ép mọi thứ thành lớp. Với logic xử lý dữ liệu thuần, hàm và kiểu đối tượng thường gọn và dễ kiểm thử hơn.
Thực hành
- Tạo lớp
SinhViencó điểm private, phương thức thêm điểm và getter điểm trung bình. - Tạo lớp trừu tượng
NhanVienvớitinhLuong(); hai lớp con toàn thời gian và bán thời gian. - Cài đặt interface
LuuTrubằng localStorage. - So sánh
privatevà#bằng cách in đối tượng ra console.
Tóm tắt bài học
- Lớp gói dữ liệu và hành vi.
- Parameter property giúp constructor ngắn gọn.
- abstract và implements tạo hợp đồng rõ ràng.
- #private là private thật khi chạy.