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 , protected và default 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 , protected và public .
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ạo và hủ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ể.