Tính Kế Thừa (Inheritance): Tái Sử Dụng Mã Nguồn Với Từ Khóa Extends

Trong các bài viết trước, chúng ta đã tìm hiểu về Lớp (Class), Đối tượng (Object) và Tính đóng gói (Encapsulation). Bài viết này sẽ đưa bạn đến một trong những trụ cột quan trọng tiếp theo của lập trình hướng đối tượng (OOP): Tính kế thừa (Inheritance).

Hình minh họa khái niệm tính kế thừa trong Java với từ khóa extends

1. Tính kế thừa là gì và tại sao cần sử dụng?

Tính kế thừa cho phép một lớp mới (gọi là lớp con - subclass) thừa hưởng các thuộc tính và phương thức từ một lớp đã tồn tại (gọi là lớp cha - superclass). Bằng cách này, bạn có thể tái sử dụng mã nguồn mà không cần phải viết lại những đoạn code giống nhau cho từng đối tượng.

Giả sử bạn cần quản lý hệ thống nhân sự cho một công ty. Cả LapTrinhVien (Developer) và NhanVienKeToan (Accountant) đều có chung các thông tin như ten, luong và cùng có hành vi làm việc. Thay vì khai báo lại các thuộc tính này ở từng lớp, bạn có thể tạo một lớp cha NhanVien chứa các đặc điểm chung, sau đó cho các lớp con kế thừa từ đó.

2. Sử dụng từ khóa extends để thiết lập quan hệ cha-con

Để thể hiện mối quan hệ kế thừa trong Java, chúng ta sử dụng từ khóa extends. Mối quan hệ này tuân theo tư duy IS-A (là một): Lập trình viên là một Nhân viên, Mèo là một Động vật.

Ví dụ minh họa cơ bản:

// Lớp cha (Superclass)
class NhanVien {
    protected String ten;
    protected double luong;

    public NhanVien(String ten, double luong) {
        this.ten = ten;
        this.luong = luong;
    }

    public void lamViec() {
        System.out.println(ten + " dang lam viec.");
    }
}

// Lớp con (Subclass) kế thừa từ NhanVien
class LapTrinhVien extends NhanVien {
    private String ngonNguSotTruong;

    public LapTrinhVien(String ten, double luong, String ngonNguSotTruong) {
        // Gọi constructor của lớp cha bằng từ khóa super
        super(ten, luong);
        this.ngonNguSotTruong = ngonNguSotTruong;
    }

    public void vietCode() {
        System.out.println(ten + " dang viet code bang " + ngonNguSotTruong);
    }
}

public class Main {
    public static void main(String[] args) {
        LapTrinhVien dev = new LapTrinhVien("Nguyen Van A", 1500, "Java");
        
        // Gọi phương thức kế thừa từ lớp cha
        dev.lamViec(); 
        
        // Gọi phương thức riêng của lớp con
        dev.vietCode();
    }
}

3. Vai trò của từ khóa super

Từ khóa super trong Java được dùng để tham chiếu trực tiếp đến đối tượng của lớp cha gần nhất. Bạn thường sử dụng super trong hai trường hợp chính:

  • Gọi Constructor của lớp cha: Cú pháp super(tham_so) phải được đặt ở dòng đầu tiên trong constructor của lớp con.
  • Gọi phương thức hoặc thuộc tính của lớp cha: Cú pháp super.tenPhuongThuc() giúp phân biệt khi lớp con định nghĩa lại một phương thức trùng tên với lớp cha.
class Animal {
    void sound() {
        System.out.println("Dong vat phat ra am thanh");
    }
}

class Cat extends Animal {
    void sound() {
        super.sound(); // Gọi lại phương thức sound() của lớp Animal
        System.out.println("Meo meo");
    }
}

4. Các nguyên tắc quan trọng khi làm việc với kế thừa

Đơn kế thừa (Single Inheritance)

Trong Java, một lớp con chỉ được kế thừa từ một lớp cha duy nhất. Java không hỗ trợ đa kế thừa trực tiếp giữa các class nhằm tránh hiện tượng xung đột phương thức (lỗi Diamond Problem).

Quyền truy cập (Access Modifiers)

Lớp con kế thừa các thành viên của lớp cha nhưng không thể truy cập trực tiếp vào các thuộc tính/phương thức private của lớp cha. Để cho phép lớp con truy cập trực tiếp, bạn nên dùng modifier protected hoặc truy cập thông qua các hàm getter/setter public.

Từ khóa final chặn kế thừa

Nếu bạn khai báo một class với từ khóa final, class đó sẽ không thể bị kế thừa bởi bất kỳ lớp nào khác. Ví dụ kinh điển trong Java là class String.

Tổng kết

Tính kế thừa giúp tối ưu hóa cấu trúc code, giảm thiểu lặp lại mã nguồn và tạo ra hệ thống phân cấp logic rõ ràng. Việc làm chủ từ khóa extends và super là nền tảng để bạn tiếp tục khám phá các tính chất nâng cao khác của OOP như Tính đa hình (Polymorphism) trong bài tiếp theo.


Nguồn tham khảo


📚 Chuỗi bài: Lộ Trình Tự Học Java Từ Con Số 0 Đến Ứng Dụng Thực Tế

Chuỗi 20 bài viết thiết kế dạng 'cầm tay chỉ việc' dành riêng cho người mới bắt đầu học lập trình Java. Lộ trình đi từ tư duy nền tảng, cú pháp cơ bản, lập trình hướng đối tượng (OOP) cho đến hoàn thiện một dự án thực tế nhỏ.

  1. 1. Java Là Giống Gì? Cài Đặt Environment (JDK & IntelliJ IDEA) Cực Nhanh
  2. 2. Giải Mã Chương Trình 'Hello World' Và Cấu Trúc Cơ Bản Của Bài Code Java
  3. 3. Biến Và Kiểu Dữ Liệu Trong Java: Cách Lưu Trữ Thông Tin Đúng Chuẩn
  4. 4. Toán Tử Trong Java: Hướng Dẫn Tính Toán Và So Sánh Chi Tiết
  5. 5. Nhập Xuất Dữ Liệu Với Scanner: Làm Cho Chương Trình Biết Tương Tác
  6. 6. Cấu Trúc Điều Kiện If-Else Và Switch-Case: Dạy Máy Tính Rẽ Nhánh Tư Duy
  7. 7. Vòng Lặp For, While Và Do-While Trong Java: Tự Động Hóa Công Việc Lặp Lại
  8. 8. Phương Thức (Method) Trong Java: Tái Sử Dụng Code Một Cách Thông Minh
  9. 9. Mảng Một Chiều (Array) Trong Java: Quản Lý Danh Sách Dữ Liệu Đơn Giản
  10. 10. Bài 10: Xử Lý Chuỗi Dữ Liệu Với String Và StringBuilder Trong Java
  11. 11. Lập Trình Hướng Đối Tượng (OOP): Lớp (Class) Và Đối Tượng (Object) Là Đâu?
  12. 12. Tính Đóng Gói (Encapsulation) Và Access Modifiers: Bảo Vệ Dữ Liệu Safe 100%
  13. 13. Tính Kế Thừa (Inheritance): Tái Sử Dụng Mã Nguồn Với Từ Khóa Extends ← Bạn đang đọc
  14. 14. Tính Đa Hình (Polymorphism): Nạp Chồng (Overloading) Và Ghi Đè (Overriding)
  15. 15. Lộ Trình Tự Học Java: Tính Trừu Tượng (Abstraction) - Abstract Class Hay Interface?
  16. 16. Xử Lý Ngoại Lệ (Exception Handling): Giúp Chương Trình Không Bị 'Sập' Đột Ngột
  17. 17. Java Collections Framework: Làm Quen Mảng Cố Định Với ArrayList
  18. 18. Lưu Trữ Cặp Dữ Liệu Key-Value Cực Kỳ Nhanh Với HashMap
  19. 19. Đọc Và Ghi File Trong Java: Lưu Trữ Dữ Liệu Lâu Dài Vào Ổ Cứng
  20. 20. Dự Án Thực Tế: Xây Dựng Ứng Dụng Quản Lý Sinh Viên Console Hoàn Chỉnh

← Bài trước: Tính Đóng Gói (Encapsulation) Và Access Modifiers: Bảo Vệ Dữ Liệu Safe 100% Bài tiếp theo: Tính Đa Hình (Polymorphism): Nạp Chồng (Overloading) Và Ghi Đè (Overriding) →

Nhận xét