
Mấy đứa hay "flex" đồ mới, nhưng có bao giờ nghĩ cái đồ đó được tạo ra từ đâu không? Trong thế giới code, đặc biệt là Java OOP, có một khái niệm cực "chill" giúp chúng ta tái sử dụng code, tạo ra những cấu trúc logic như mấy cái cây phả hệ vậy đó. Đó chính là Parent Class – hay còn gọi là lớp cha, lớp cơ sở.
Parent Class là gì và để làm gì?
Tưởng tượng Parent Class như một bản thiết kế "MVP" (Minimum Viable Product) cho một nhóm đối tượng có chung đặc điểm. Ví dụ, bản thiết kế XeCộ. Tất cả xe cộ đều có bánh, có động cơ, có thể chạy. Đó là những thứ cơ bản nhất.
Parent Class chứa những thuộc tính (variables) và hành vi (methods) chung mà các lớp con (Child Classes) sẽ "thừa hưởng" (inherit) từ nó. Nó giúp chúng ta tránh lặp đi lặp lại code (DRY - Don't Repeat Yourself), tiết kiệm thời gian, công sức và làm cho code "sạch" hơn, dễ bảo trì hơn.
Mục đích chính của Parent Class:
- Tái sử dụng code: Viết một lần, dùng nhiều nơi. Như việc sản xuất linh kiện chung cho nhiều dòng xe vậy.
- Tạo ra cấu trúc phân cấp: Giúp tổ chức code một cách logic, dễ hiểu, dễ quản lý.
- Đa hình (Polymorphism): Cái này "level up" hơn, nhưng nhờ có Parent Class mà chúng ta có thể coi các Child Class như thể chúng là Parent Class, giúp code linh hoạt hơn rất nhiều.
Code Ví Dụ Minh Hoạ
Để dễ hình dung, hãy xem ví dụ về một Parent Class là Vehicle (Xe Cộ) và các Child Class là Car (Ô Tô) và Motorcycle (Xe Máy):
// Parent Class: XeCộ
class Vehicle {
String brand;
int year;
public Vehicle(String brand, int year) {
this.brand = brand;
this.year = year;
}
public void startEngine() {
System.out.println(brand + " đời " + year + " khởi động động cơ. Vroom vroom!");
}
public void stopEngine() {
System.out.println(brand + " đời " + year + " tắt máy.");
}
public void displayInfo() {
System.out.println("Đây là một chiếc " + brand + " sản xuất năm " + year + ".");
}
}
// Child Class: ÔTô, kế thừa từ Vehicle
class Car extends Vehicle {
int numberOfDoors;
public Car(String brand, int year, int numberOfDoors) {
super(brand, year); // Gọi constructor của Parent Class
this.numberOfDoors = numberOfDoors;
}
public void honk() {
System.out.println(brand + " bóp còi: Beep beep!");
}
@Override // Annotation báo hiệu override method từ Parent Class
public void displayInfo() {
super.displayInfo(); // Gọi method từ Parent Class để tái sử dụng
System.out.println("Nó có " + numberOfDoors + " cửa.");
}
}
// Child Class: XeMáy, kế thừa từ Vehicle
class Motorcycle extends Vehicle {
boolean hasSideCar;
public Motorcycle(String brand, int year, boolean hasSideCar) {
super(brand, year);
this.hasSideCar = hasSideCar;
}
public void wheelie() {
System.out.println(brand + " đang bốc đầu! Quá cháy!");
}
@Override
public void displayInfo() {
super.displayInfo();
if (hasSideCar) {
System.out.println("Đặc biệt, nó có thêm thùng xe (sidecar).");
} else {
System.out.println("Đây là xe máy 2 bánh thông thường.");
}
}
}
// Lớp chính để chạy thử
public class Garage {
public static void main(String[] args) {
Car myCar = new Car("Honda Civic", 2023, 4);
Motorcycle myBike = new Motorcycle("Yamaha Exciter", 2020, false);
System.out.println("--- Thông tin Xe Hơi ---");
myCar.displayInfo(); // Gọi phương thức đã override
myCar.startEngine(); // Kế thừa từ Vehicle
myCar.honk(); // Phương thức riêng của Car
myCar.stopEngine(); // Kế thừa từ Vehicle
System.out.println("\n--- Thông tin Xe Máy ---");
myBike.displayInfo(); // Gọi phương thức đã override
myBike.startEngine(); // Kế thừa từ Vehicle
myBike.wheelie(); // Phương thức riêng của Motorcycle
myBike.stopEngine(); // Kế thừa từ Vehicle
// Ví dụ về đa hình (Polymorphism) - Một biến kiểu Parent Class có thể chứa Child Class
System.out.println("\n--- Đa hình ---");
Vehicle generalVehicle1 = new Car("Toyota Camry", 2022, 4);
Vehicle generalVehicle2 = new Motorcycle("Harley-Davidson", 2021, true);
generalVehicle1.displayInfo(); // Gọi displayInfo của Car
generalVehicle2.displayInfo(); // Gọi displayInfo của Motorcycle
}
}

Giải thích Code Ví Dụ
VehiclelàParent Class(lớp cha). Nó định nghĩabrand,yearvà các phương thứcstartEngine(),stopEngine(),displayInfo()mà mọi loại xe đều có.CarvàMotorcyclelàChild Classes(lớp con). Chúng dùng từ khóaextends Vehicleđể nói rằng: "Tui là Car, tui kế thừa hết mọi thứ từ Vehicle, nhưng tui có thêm mấy cái riêng của tui nữa."super(brand, year)trong constructor củaCarvàMotorcycledùng để gọi constructor củaParent Class(Vehicle) để khởi tạo các thuộc tính chung.@Overridelà một annotation "cool" báo hiệu rằng chúng ta đang định nghĩa lại một phương thức đã có ở lớp cha. Đây là cách để các lớp con "custom" lại hành vi của lớp cha cho phù hợp với mình.super.displayInfo()cho phép chúng ta gọi lại phương thứcdisplayInfo()của lớp cha ngay bên trong phương thứcdisplayInfo()đã được override ở lớp con. Như kiểu "kế thừa xong rồi, giờ thêm thắt của riêng mình vào thôi."- Phần
Garagecho thấy cách chúng ta tạo ra các đối tượng từ lớp con và truy cập cả các phương thức của lớp cha (startEngine(),stopEngine()) lẫn các phương thức riêng của lớp con (honk(),wheelie()). - Ví dụ về đa hình cho thấy một biến kiểu
Vehiclecó thể chứa đối tượngCarhoặcMotorcycle, và khi gọidisplayInfo(), Java sẽ tự động biết gọi phương thức của lớp con tương ứng. "Chất lừ" chưa?
Mẹo hay (Best Practices) khi dùng Parent Class
- Đừng lạm dụng: Kế thừa là mạnh, nhưng đừng dùng bừa bãi. Một hệ thống kế thừa quá sâu (nhiều tầng lớp cha-con-cháu) có thể rất khó quản lý và debug. Hãy giữ cho cây phả hệ code của bạn "gọn gàng".
- "Is-A" Relationship: Chỉ dùng kế thừa khi có mối quan hệ "là một" (is-a). Ví dụ: "Car IS-A Vehicle", "Dog IS-A Animal". Nếu không phải, có lẽ bạn cần cân nhắc Composition (Has-A relationship) hoặc Interface.
- Parent Class nên là Abstract hoặc Interface: Thường thì,
Parent Classlý tưởng nên là mộtAbstract ClasshoặcInterfaceđể định nghĩa một "hợp đồng" chung mà các lớp con phải tuân theo, thay vì một lớp cụ thể. Cái này sẽ học sau, nhưng cứ nhớ trước nha. - Hạn chế truy cập trực tiếp: Đừng để các thuộc tính của
Parent Classlàpublichết. Dùngprotectedhoặcprivatevà cung cấpgetter/setternếu cần. Giữ cho "gia đình" code của bạn có sự riêng tư nhất định.
Ứng dụng thực tế
Parent Class được dùng "xuyên lục địa" trong mọi ngóc ngách của lập trình:
- Android/iOS UI Frameworks: Các button, text field, image view... đều là các
Child Classcủa mộtParent Classchung nhưView(Android) hoặcUIView(iOS). Chúng kế thừa các thuộc tính cơ bản như kích thước, vị trí, khả năng hiển thị, sau đó thêm các chức năng riêng. - Game Development: Trong game, bạn có thể có
Parent ClasslàCharacter(nhân vật), với các thuộc tính như máu, mana, vị trí. Sau đó cácChild ClassnhưWarrior,Mage,Archersẽ kế thừa và thêm các kỹ năng, vũ khí riêng. - Hệ thống Ngân hàng:
AccountlàParent Classvới số dư, chủ tài khoản.CheckingAccount(tài khoản vãng lai) vàSavingsAccount(tài khoản tiết kiệm) làChild Classes, mỗi loại có thêm các quy tắc riêng về lãi suất, phí.
Khi nào nên dùng Parent Class (và khi nào không)?
Nên dùng khi:
- Bạn có một tập hợp các đối tượng có nhiều điểm chung và bạn muốn tái sử dụng logic đó.
- Bạn muốn tạo một cấu trúc phân cấp rõ ràng cho các đối tượng của mình, giúp code dễ đọc, dễ hiểu hơn.
- Bạn muốn tận dụng sức mạnh của đa hình (polymorphism) để viết code linh hoạt hơn, dễ mở rộng hơn. Ví dụ, bạn có thể tạo một danh sách
List<Vehicle>chứa cảCarvàMotorcycle, rồi chạy vòng lặp gọistartEngine()cho tất cả mà không cần quan tâm đó là loại xe cụ thể nào.
Thử nghiệm: Hãy tự viết một Parent Class là Shape (hình dạng) với các thuộc tính như màu sắc, và phương thức calculateArea(). Sau đó tạo các Child Class như Circle (hình tròn) và Rectangle (hình chữ nhật) kế thừa Shape, override phương thức calculateArea() để tính diện tích riêng của từng hình. Bạn sẽ thấy sức mạnh của nó ngay!
Parent Class không chỉ là một khái niệm, nó là một "superpower" giúp bạn xây dựng những hệ thống code lớn, phức tạp một cách có tổ chức và hiệu quả. Hãy làm chủ nó, và bạn sẽ thấy code của mình "level up" đáng kể!
Thuộc Series: Java – OOP
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!