Parent Class là gì? Từ A-Z về Kế Thừa trong Java OOP
Java – OOP

Parent Class là gì? Từ A-Z về Kế Thừa trong Java OOP

Author

Admin System

@root

Ngày xuất bản

19 Mar, 2026

Lượt xem

1 Lượt

Parent Class

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:

  1. 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.
  2. 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ý.
  3. Đ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 ClassVehicle (Xe Cộ) và các Child ClassCar (Ô 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
    }
}
Illustration

Giải thích Code Ví Dụ

  • VehicleParent Class (lớp cha). Nó định nghĩa brand, year và các phương thức startEngine(), stopEngine(), displayInfo() mà mọi loại xe đều có.
  • CarMotorcycleChild Classes (lớp con). Chúng dùng từ khóa extends 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ủa CarMotorcycle dùng để gọi constructor của Parent Class (Vehicle) để khởi tạo các thuộc tính chung.
  • @Override là 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ức displayInfo() của lớp cha ngay bên trong phương thức displayInfo() đã đượ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 Garage cho 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 Vehicle có thể chứa đối tượng Car hoặc Motorcycle, và khi gọi displayInfo(), 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

  1. Đừ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".
  2. "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.
  3. Parent Class nên là Abstract hoặc Interface: Thường thì, Parent Class lý tưởng nên là một Abstract Class hoặc Interface để đị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.
  4. Hạn chế truy cập trực tiếp: Đừng để các thuộc tính của Parent Classpublic hết. Dùng protected hoặc private và cung cấp getter/setter nế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 Class của một Parent Class chung như View (Android) hoặc UIView (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 ClassCharacter (nhân vật), với các thuộc tính như máu, mana, vị trí. Sau đó các Child Class như Warrior, Mage, Archer sẽ kế thừa và thêm các kỹ năng, vũ khí riêng.
  • Hệ thống Ngân hàng: AccountParent Class vớ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ả CarMotorcycle, rồi chạy vòng lặp gọi startEngine() 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 ClassShape (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é!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!