Tính kế thừa (inheritance) trong Java

Đây là bài 27/62 bài của series môn học Ngôn ngữ lập trình Java

1. Kế thừa (inheritance) là gì?

Bản chất kế thừa (inheritance) là phát triển lớp mới dựa trên các lớp đã có. Xây dựng các lớp mới có sẵn các đặc tính của lớp cũ, đồng thời lớp mới có thể mở rộng các đặc tính của nó.

Ví dụ:

Lớp Người có các thuộc tính như tên, tuổi, chiều cao, cân nặng,…; các phương thức như ăn, ngủ, chơi,…

Lớp Sinh Viên thừa kế từ lớp Người, thừa kế được các thuộc tính tên, tuổi, chiều cao, cân nặng,…; các phương thức ăn, ngủ, chơi,…Bổ sung thêm các thuộc tính như mã số sinh viên, số tín chỉ tích lũy,…, các phương thức như tham dự lớp học, thi…

Ví dụ kế thừa trong Java

Lớp kế thừa gọi là lớp con (child, subclass), lớp dẫn xuất (derived class). Lớp được kế thừa gọi là lớp cha (parent, superclass), lớp cơ sở (base class).

Mối quan hệ kế thừa: Lớp con là một loại (is-a-kind-of) của lớp cha, kế thừa các thành phần dữ liệu và các hành vi của lớp cha. Có thể khai báo thêm thuộc tính, phương thức cho phù hợp với mục đích sử dụng mới.

Ví dụ: Lớp SinhVien kế thừa từ lớp Nguoi, lớp GiaoVien kế thừa từ lớp Nguoi thì một đối tượng SinhVien là một Nguoi, một đối tượng GiaoVien là một Nguoi. Nhưng một đối tượng Nguoi chưa chắc là SinhVien bởi vì có thể đối tượng Nguoi đó là GiaoVien. Tương tự, môt đối tượng Nguoi chưa chắc là GiaoVien bởi vì có thể đối tượng Nguoi đó là SinhVien.

Bản chất kế thừa là một kỹ thuật tái sử dụng mã nguồn thông qua lớp.

Ví dụ: Lớp SinhVien tái sử dụng được các thuộc tính như tên, tuổi… và các phương thức của lớp Nguoi.

2. Khai báo kế thừa (inheritance) trong Java

Cú pháp:

<Lớp con> extends <Lớp cha>{
     //thân lớp con
}

Ví dụ:

class Nguoi {
    String name;
    //hàm đi chơi
    void diChoi(){
        System.out.println(name + " di choi thoi!");
    }
}
class SinhVien extends Nguoi {
    int studentId;
    //hàm đi học
    void diHoc(){
        System.out.println(name + " mssv: " + studentId + " di hoc thoi!");
    }
}

public class Main {
    public static void main(String args[]){
        SinhVien sv1 =  new SinhVien();
        sv1.name = "An";
        sv1.studentId = 123456789;
        sv1.diChoi();
        sv1.diHoc();
    }
}
Kết quả
An di choi thoi!
An mssv: 123456789 di hoc thoi!

Trong ví dụ trên, lớp SinhVien kế thừa từ lớp Nguoi. Lớp SinhVien kế thừa thuộc tính String name và hàm diChoi() từ lớp Nguoi.

Một câu hỏi đặt ra là lớp con kế thừa được những gì từ lớp cha?

Lớp con kế thừa các thành viên được khai báo là public, protected mặc định (default) của lớp cha. Không kế thừa được các thành viên private.

Các bạn nên đọc bài Chỉ định truy cập (access modifier) của thành viên thuộc lớp trong Java để hiểu rõ về các access modifier trong Java là default, private, protected public.

Bảng phạm vi truy cập và nguyên lý kế thừa trong Java
 publicprotectedmặc địnhprivate
Cùng lớp
Lớp bất kỳ cùng gói
Lớp con khác gói
Lớp bất kỳ khác gói

Bảng này giống như “khẩu quyết nội công tâm pháp”, các bạn phải ngẫm nghĩ, bắt buộc phải nhớ rõ và hiểu nó.

class LopCha{
    private String bienA;//biến private
    String bienB;//biến default
    protected int bienC;//biến protected
    public int bienD;//biến public
    
    private void ham1(){//hàm private
        System.out.println("Ham private.");
    }
    void ham2(){//hàm default
        System.out.println("Ham default.");
    }
    protected void ham3(){////hàm protected
        System.out.println("Ham protected.");
    }
    public void ham4(){//hàm public
        System.out.println("Ham public.");
    }
}
class LopCon extends LopCha{
}
public class Test{
    public static void main(String[] args) {
        LopCon a = new LopCon();
        a.bienA = "abc";//lỗi, không kế thừa được biến private
        a.bienB = "xyz";//kế thừa được biến default
        a.bienC = 9;//kế thừa được biến protected
        a.bienD = 9;//kế thừa được biến public
        a.ham1();//lỗi, không kế thừa được hàm private
        a.ham2();//kế thừa được hàm default
        a.ham3();//kế thừa được hàm protected
        a.ham4();//kế thừa được hàm public
    }
}
Các phương thức không được phép kế thừa:

– Các phương thức khởi tạo và hủy:

    • Làm nhiệm vụ khởi tạo và gỡ bỏ các đối tượng.
    • Chúng chỉ biết cách làm việc với từng lớp cụ thể.

– Toán tử gán “=”, làm nhiệm vụ giống như phương thức khởi tạo.

3. Các loại kế thừa trong Java

Đơn kế thừa (single inheritance)

Một lớp con kế thừa từ một lớp cha.

Single inheritance in Java

Kế thừa nhiều cấp (multilevel inheritance)

Một lớp con kế thừa từ một lớp cha. Lớp cha đó lại kế thừa từ một lớp khác.

Multilevel inheritance in Java

Kế thừa phân cấp (hierarchical inheritance)

Nhiều lớp con kế thừa từ một lớp cha. Các lớp con có cùng lớp cha gọi là các lớp anh chị em (siblings).

Hierarchical inheritance in Java

Java không hỗ trợ đa kế thừa (multiple Inheritance)

Trong Java không hỗ trợ đa kế thừa, tức là một lớp con kế từ từ nhiều lớp cha.

Minh họa multiple inheritance

Nhưng trong Java có thể thực hiện đa kế thừa bằng cách sử dụng interface, chứ không đa kế thừa từ lớp (class) được để tránh những mơ hồ không cần thiết khi kế thừa.

Kế thừa lai (hybrid inheritance)

Kế thừa lai là sự kế hợp giữa 2 hoặc nhiều hơn 2 loại kế thừa.

Minh họa hybrid inheritance

Ở trên là ví dụ kết hợp giữa kế thừa phần cấp và đa kế thừa (phải sử dụng interface).

Lưu ý:

Nếu một lớp không được định nghĩa là lớp con của một lớp khác thì mặc định nó là lớp con trực tiếp của lớp Object. Lớp này được định nghĩa trong package chuẩn java.lang, chứa một số phương thức hữu ích kế thừa lại cho tất cả các lớp.

Kế thừa Object Class trong Java
Kế thừa Object Class trong Java

4. Khai báo và hủy đối tượng (object) trong kế thừa

Khởi tạo đối tượng: Lớp cha được khởi tạo trước lớp con. Các phương thức khởi tạo của lớp con luôn gọi phương thức khởi tạo của lớp cha ở câu lệnh đầu tiên.

    • Tự động gọi (ngầm định – implicit): khi lớp cha có phương thức khởi tạo mặc định.
    • Gọi trực tiếp (tường minh – explicit): sử dụng từ khóa super.
class TuGiac {
    public TuGiac() {
        System.out.println("Lop cha TuGiac()");
    }
}
class HinhVuong extends TuGiac {
    public HinhVuong() {
        // Tu dong goi TuGiac()
        System.out.println("Lop con HinhVuong()");
    }
}
public class Test {
    public static void main(String arg[]) {
        HinhVuong hv = new HinhVuong();
    }
}
Kết quả
Lop cha TuGiac()
Lop con HinhVuong()

Hủy bỏ đối tượng: Ngược lại so với khởi tạo đối tượng.

5/5 - (1 bình chọn)
Bài trước và bài sau trong môn học<< Xây dựng lớp trong Java với nạp chồng (overloading) và kết tập (aggregation)Chỉ định truy cập (access modifier) của thành viên thuộc lớp trong Java >>
Chia sẻ trên mạng xã hội:

Trả lời

Lưu ý:

1) Vui lòng bình luận bằng tiếng Việt có dấu.

2) Khuyến khích sử dụng tên thật và địa chỉ email chính xác.

3) Mọi bình luận trái quy định sẽ bị xóa bỏ.