1. Tính kế thừa trong Java là gì?

Tính kế thừa – Inheritance trong Java là sự liên quan giữa các class với nhau. Trong đó có class cha (superclass) và class con (subclass). Khi kế thừa class con được hưởng tất cả các phương thức và thuộc tính của class cha.

Ta có thể hiểu đơn giản nhất là kế thừa có nghĩa là thừa hưởng lại, ví dụ như tài sản của ba mẹ sẽ được giao lại cho con cái vậy. Việc sử dụng kế thừa nhằm tái sử dụng code đã viết trước đó, thuận tiện trong việc bảo trì và nâng cấp chương trình. Còn phạm vi truy cập thì tùy vào access_modifier của thuộc tính phương thức đó.

Có 3 dạng kế thừa chính đó là:

  • Kế thừa từ Class
  • Kế thừa từ lớp trừu tượng (Abstract class)
  • Kế thừa từ Interface

2. Cú pháp của tính kế thừa trong Java

Để khai báo tính kế thừa trong Java ta sử dụng từ khóa expands . Cú pháp chính là:

class SubClassName extends SuperClassName {
    //code
}

Trong đó:

  • SubClassName là tên của class con các bạn muốn khai báo.
  • SuperClassName là tên của class cha các bạn muốn kế thừa.

Từ khóa extends chỉ rằng ta đang tạo 1 lớp mới mà kế thừa từ 1 lớp đang tồn tại. Trong Java, 1 lớp mà được kế thừa được gọi là 1 lớp cha. Lớp mới được gọi là lớp con.

Ví dụ: Khai báo Employee là lớp cha và Programmer là lớp con

class Employee {
  float salary = 40000;
}
class Programmer extends Employee {
  int bonus = 10000;
  public static void main(String args[]) {
    Programmer p = new Programmer();
    System.out.println("Lương là :" + p.salary);
    System.out.println("Thưởng là :" + p.bonus);
  }
}

Kết quả

Lương là :40000.0
Thưởng là :10000

Hoặc với class car là lớp con kế thừa phương thức và thuộc tính từ class Vehicle là lớp cha

class Vehicle {
  protected String brand = "Ford";
  public void honk() {
    System.out.println("Tuut, tuut!");
  }
}

class Car extends Vehicle {
  private String modelName = "Mustang";
  public static void main(String[] args) {
    Car myFastCar = new Car();
    myFastCar.honk();
    System.out.println(myFastCar.brand + " " + myFastCar.modelName);
  }
}

Kết quả

Tuut, tuut!
Ford Mustang

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

Có 3 kiểu kế thừa chính trong Java là:

  • Đơn kế thừa
  • Kế thừa nhiều cấp
  • Kế thừa thứ bậc

3.1. Đơn kế thừa

Đơn kế thừa – Single Inheritance là việc kế thừa mà một lớp chỉ kế thừa từ đúng một lớp khác. Một lớp con kế thừa duy nhất từ một lớp cha.

Cú pháp cơ bản :

class lopcon : phamvidulieu lopcha
{
  // code
};

Ví dụ:

class Animal {
    void eat() {
        System.out.println("eating...");
    }
}
 
class Dog extends Animal {
    void bark() {
        System.out.println("barking...");
    }
}
 
public class Main {
    public static void main(String args[]) {
        Dog d = new Dog();
        d.bark();
        d.eat();
    }
}

Kết quả

barking...
eating...

3.2. Kế thừa nhiều cấp

Kế thừa nhiều cấp – Multiple Inheritance có nghĩa việc 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. Nó giống như là tính chất bắc cầu vậy.

Ví dụ:

class Animal {
    void eat() {
        System.out.println("eating...");
    }
}
class Dog extends Animal {
    void bark() {
        System.out.println("barking...");
    }
}
 
class BabyDog extends Dog {
    void weep() {
        System.out.println("weeping...");
    }
}
public class Main {
    public static void main(String args[]) {
        BabyDog d = new BabyDog();
        d.weep();
        d.bark();
        d.eat();
    }
}

Kết quả

weeping...
barking...
eating...

3.3. Kế thừa thứ bậc

Kế thừa thứ bậc – Hierarchical Inheritance nghĩa là việc kế thừa từ nhiều lớp con tới 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).

Ví dụ:

class Animal {
    void eat() {
        System.out.println("eating...");
    }
}
class Dog extends Animal {
    void bark() {
        System.out.println("barking...");
    }
}
class Cat extends Animal {
    void meow() {
        System.out.println("meowing...");
    }
}
public class Main {
    public static void main(String args[]) {
        Cat c = new Cat();
        c.meow();
        c.eat();
    }
}

Kết quả

meowing...
eating...

3.4. Một số loại kế thừa khác

Đa kế thừa là 1 tính năng của ngôn ngữ C++. Trong đấy 1 lớp có thể kế thừa từ nhiều hơn 1 lớp khác. Nghĩa là 1 lớp con được kế thừa từ nhiều hơn 1 lớp cơ sở. Nhưng 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.

Tuy nhiên 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.

Ví dụ:

class A {
    void msg() {
        System.out.println("Hello");
    }
}
 
class B {
    void msg() {
        System.out.println("Welcome");
    }
}
 
public class C extends A,B { 
 public static void main(String args[]) {
        C obj = new C();
        obj.msg();
    }
}

Một lỗi sẽ hiển thị ra kiểu như vậy

Compile Time Error

Cùng với đó ta cũng có kiểu kế thừa lai – Hybrid (Virtual) Inheritance còn gọi là kế thừa ảo. Nó là sự kế hợp giữa 2 hoặc nhiều hơn 2 loại kế thừa.

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.

4. Từ khóa super trong Java

Trong trường hợp class con khai báo lại các phương thức và thuộc tính trong class cha mà vẫn muốn đứng ở class con có thể gọi lại các class bị ghi đè đó trong class cha thì chúng ta sử dụng từ khóa super . Ngoài ra ta cũng có thể dùng để:

  • Phân biệt các thành phần có cùng tên giữa lớp cha và lớp con
  • Gọi hàm tạo của lớp cha từ lớp con

4.1. Phân biệt các thành phần có cùng tên giữa lớp cha và lớp con

Nếu chúng ta có một lớp con thừa kế từ một lớp cha và các thành phần của lớp cha có cùng tên với các thành phần của lớp con thì để phân biệt các thành phần của lớp cha từ lớp con, chúng ta sẽ sử dụng từ khóa super với cú pháp như sau:

super.tên_thuộc_tính;
super.tên_phương_thức();

Ví dụ:

  • File Superclass.java
package vidu;
 
public class Superclass {
    int number = 10;
 
    public void hienThi() {
        System.out.println("Đây là phương thức hienThi() của lớp cha");
    }
}
  • File Subclass.java
package vidu;
 
public class Subclass extends Superclass {
    int number = 20;
 
    public void hienThi() {
        System.out.println("Đây là phương thức hienThi() của lớp con");
    }
     
    public void subclassMethod() {
        Subclass subclass = new Subclass();
         
        // gọi phương thức hienThi() của lớp cha
        // sử dụng từ khóa super()
        super.hienThi();
         
        // gọi phương thức hienThi() của lớp con
        subclass.hienThi();
         
        // hiển thị giá trị biến number của lớp cha
        System.out.println("Giá trị biến number của lớp cha = " + super.number);
         
        // hiển thị giá trị biến number của lớp con
        System.out.println("Giá trị biến number của lớp con = " + subclass.number);
    }
 
 
    public static void main(String[] args) {
        Subclass objSubclass = new Subclass();
        objSubclass.subclassMethod();
    }
 
}

Kết quả

Đây là phương thức hienthi() của lớp cha
Đây là phương thức hienthi() của lớp con
Giá trị biến number của lớp cha = 10
Giá trị biến number của lớp con = 20

4.2. Gọi hàm tạo của lớp cha

Nếu chúng ta có 1 lớp là lớp con của một lớp khác thì lớp con đó có thể tự động gọi được hàm tạo mặc định của lớp cha. Nhưng trong trường hợp chúng ta muốn gọi hàm tạo có đối số của lớp cha, chúng ta cần sử dụng từ khóa super với cú pháp như sau:

super(tên_đối_số);

Ví dụ:

  • File Superclass.java
package vidu;
 
public class Superclass {
     
    public Superclass(int number) {
        System.out.println("Đây là hàm tạo có đối số của lớp Superclass, giá trị"
                + " biến number = " + number);
    }
}
  • File Subclass.java
package vidu;
 
public class Subclass extends Superclass {
 
    public Subclass(int number) {
        super(number);  // gọi hàm tạo của lớp Superclass
        System.out.println("Đây là hàm tạo của lớp Subclass, giá trị biến number = " + number);
    }
 
    public static void main(String[] args) {
        Subclass subclass = new Subclass(10);
    }
 
}

Kết quả

Đây là hàm tạo có đối số của lớp Superclass, giá trị biến number = 10
Đây là hàm tạo của lớp Supclass, giá trị biến number = 10

5. Những thứ kế thừa được của lớp con từ lớp cha

Lớp con kế thừa các thành viên được khai báo là public , protecteddefault của lớp cha. Không kế thừa được các thành viên private . Ta có thể đọc lại bài Phạm vi truy cập trong Java để hiểu rõ hơn về các access modifier trong Java là default , private , protectedpublic .

Ta có bảng phạm vi truy cập và nguyên lý kế thừa trong Java

public protected default private
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

Một số phương thức không được phép kế thừa là khởi tạohủy . Vì chúng 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ể.