TỔNG QUAN
CẤU TRÚC ĐIỀU KHIỂN
VÒNG LẶP
CHUỖI VÀ MẢNG
COLLECTIONS
THƯ VIỆN QUAN TRỌNG
HƯỚNG ĐỐI TƯỢNG
XỬ LÝ LUỒNG
EXCEPTION
LÀM VIỆC VỚI FILE
THAM KHẢO
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

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

Trong bài trước, tôi đã giới thiệu đến các bạn tính đóng gói của lập trình hướng đối tượng trong Java. Sang bài này, tôi sẽ giới thiệu đến các bạn tính chất cơ bản tiếp theo đó là tính kế thừa (Inheritance) và cách vận dụng tính chất này trong lập trình. Cuối bài này, tôi sẽ đưa ra một số bài tập cho các bạn luyện tập!

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

1. Khái niệm tính kế thừa

Khái niệm tổng quát hóa và đặc biệt hóa

Quan hệ tổng quát hóa và đặc biệt hóa là 1 quan hệ thực sự rất tự nhiên và thông dụng trong thế giới thực. Đối tượng đặc biệt hóa của một dạng đối tượng tổng quát sẽ có đầy đủ tính chất của loại đối tượng ban đầu và có thêm các đặc điểm riêng của nó. Ví dụ hình chữ nhật lại là khái niệm tổng quát hóa của hình vuông, và ngược lại hình vuông là một trường hợp đặc biệt của hình chữ nhật. Hình vuông có đầy đủ các tính chất của hình chữ nhật bởi vì hình chữ nhật là tổng quát của hình vuông; hơn nữa, hình vuông có những tính chất đặc biệt mà hình chữ nhật không có bởi vì hình vuông được đặc biệt hóa từ hình chữ nhật.

Rất nhiều lớp đối tượng trong thế giới thực là đặc biệt hóa hay tổng quát hóa của lớp đối tượng khác. Quan hệ tổng quát hóa và đặc biệt hóa đóng vai trò rất quan trọng, hầu hết các ngôn ngữ lập trình hướng đối tượng đều hỗ trợ người lập trình cài đặt quan hệ này.

Khái niệm tính kế thừa

Khái niệm "kế thừa" thường được dùng trong các ngôn ngữ lập trình hướng đối tượng để chuyển quan hệ tổng quát hóa và đặc biệt hóa của thế giới thực vào các chương trình máy tính. Tính kế thừa cho phép ta xây dựng một lớp mới dựa trên các định nghĩa của một lớp đã có.

Bài viết này được đăng tại [free tuts .net]

Nếu một lớp A là lớp đặc biệt hóa của lớp B (nghĩa là lớp B là lớp tổng quát hóa của lớp A) thì trong lập trình hướng đối tượng lớp A được cài đặt là lớp kế thừa của lớp B (nói ngắn gọn là "lớp A kế thừa lớp B"). Khi lớp A kế thừa lớp B thì lớp B được gọi là "lớp cơ sở" hay "lớp cha" (trong mối quan hệ kế thừa đang xét), còn lớp A thì được gọi là "lớp kế thừa", "lớp con" hay "lớp dẫn xuất".

Lợi ích của tính kế thừa

Sau đây là một số lợi ích có được khi vận dụng tính kế thừa trong lập trình:

  • Lớp con (lớp A) có thể tận dụng lại các thuộc tính và phương thức của lớp cha (lớp B) (nghĩa là các thuộc tính và phương thức của lớp B có thể được tái sử dụng bởi lớp A).
  • Lớp A có thể định nghĩa thêm thuộc tính và phương thức mới của riêng nó và có thể định nghĩa lại (hay còn gọi là ghi đè phương thức, overriding) phương thức được kế thừa từ lớp B cho phù hợp với mục đích của nó.

Các dạng kế thừa

Trong Java, chúng ta 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) và kế thừa từ Interface. Trong phạm vi của bài này, chúng ta sẽ chỉ tìm hiểu về dạng kế thừa từ Class. Sang các bài sau, tôi sẽ trình bày về 2 dạng kế thừa còn lại.

2. Xây dựng lớp con và lớp cha trong tính kế thừa

Khi lập trình với tính kế thừa trong Java, việc đầu tiên và quan trọng nhất đó là chúng ta phải xây dựng được lớp con và lớp cha dựa vào những thông tin đã có. Vậy để làm được việc này, chúng ta sẽ làm như sau:

Xây dựng lớp cha: những thông tin nào chung giữa các đối tượng (bao gồm thuộc tính và phương thức) thì chúng ta tập hợp lại tạo thành lớp cha.

Xây dựng lớp con: những thông tin nào chỉ có trong từng đối tượng cụ thể thì chúng ta tập hợp lại tạo thành lớp con.

2. Ví dụ về tính kế thừa

Để cài đặt tính kế thừa, chúng ta sẽ sử dụng từ khóa extends. Giả sử chúng ta có 1 lóp A kế thừa từ lớp B thì chúng ta sẽ khai báo lớp B theo cú pháp như sau:

Cú pháp
public class A {
	...
}


public class B extends A {
	...
}

Để hiểu hơn về tính kế thừa, các bạn theo dõi ví dụ sau:

Calculate.java
package vidu;

public class Calculation {
	protected int c;
	public void phepCong(int a, int b) {
		c = a + b;
		System.out.println("Tổng hai số = " + c);
	}
	
	public void phepTru(int a, int b) {
		c = a - b;
		System.out.println("Hiệu hai số = " + c);
	}
}

MyCalculation.java
package vidu;

public class MyCalculation extends Calculation {
	public void phepNhan(int a, int b) {
		c = a * b;
		System.out.println("Tích 2 số = " + c);
	}
	
	public void phepLuyThua(int a, int b) {
		c = (int) Math.pow(a, b);
		System.out.println(a + "^" + b + " = " + c);
	}
	
	public static void main(String[] args) {
		int a = 12, b = 2;
		MyCalculation myCalculation = new MyCalculation();
		myCalculation.phepCong(a, b);
		myCalculation.phepTru(a, b);
		myCalculation.phepNhan(a, b);
		myCalculation.phepLuyThua(a, b);	
	}
}

Kết quả sau khi biên dịch chương trình:

ketqua vi du tinh ke thua PNG

Trong ví dụ này, tôi tạo ra 2 lớp CalculationMyCalculation kế thừa từ lớp Calculation. Trong lớp Calculation tôi có khai báo 1 thuộc tính c có kiểu int và phạm vi truy cập là protected nhằm mục đích cho phép các lớp con của lớp này có thể dùng lại thuộc tính c (các bạn có thể dùng từ khóa public hoặc không dùng từ khóa nhưng không được khai báo là private) cùng với 2 phương thức là phepCong(int a, int b) để thực hiện phép cộng và phepTru(int a, int b) để thực hiện phép trừ.

Lớp MyCalculation là lớp kế thừa từ lớp Calculation. Lớp này dùng lại thuộc tính c và 2 phương thức phepCong(int a, int b)phepTru(int a, int b) của lớp Calculation, vì vậy trong lớp MyCalculation không khai báo lại c, phepCong(int a, int b)phepTru(int a, int b) vì tất cả chúng đều được lấy lại của lớp Calculation. Ngoài ra, lớp MyCalculation còn khai báo 2 phương thức riêng của nó đó là phepNhan(int a, inb b) phepLuyThua(int a, int b) để thực hiện phép nhân và phép lũy thừa hai số.

Hàm main() của lớp MyCalculation minh họa việc khai báo và sử dụng đối tượng myCalculation (kiểu MyCalculation). Trong hàm này, tôi có 2 dòng code myCalculation.phepCong(a, b);myCalculation.phepTru(a, b); dùng để gọi phương thức phepCong(int a, int b)phepTru(int a, int b), mã nguồn của 2 phương thức này được kế thừa từ lớp Calculation mà không cần viết lại cho lớp MyCalculation.

Lưu ý:

  • Qua ví dụ trên, chúng ta có thể rút ra kết luận là một lớp con có thể kế thừa tất cả các thành phần của lớp cha (thuộc tính, phương thức,...) nhưng không thể kế thừa được lớp con. Tuy nhiên, hàm tạo của lớp cha có thể được gọi từ lớp con thông qua từ khóa super.
  • Một lớp con chỉ có thể kế thừa trực tiếp từ một lớp cha. Nếu lớp con không kế thừa từ một lớp cha nào thì mặc định nó sẽ kế thừa từ một lớp cha tên là Object.

3. Từ khóa super

Từ khóa super được sử dụng trong các trường hợp sau:

  • Nó được sử 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.
  • Nó được sử dụng để gọi hàm tạo của lớp cha từ lớp con.

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:

Cú pháp
super.tên_thuộc_tính;
super.tên_phương_thức();

Dưới đây là ví dụ minh họa cách sử dụng từ khóa super trong trường hợp này.

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");
	}
}

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ả sau khi biên dịch chương trình:

ketqua vi du tu khoa super 1 PNG

Giải thích hoạt động của chương trình trên.

Trong ví dụ này chúng ta có 2 lớp: lớp cha tên là Superclass và lớp con tên là Subclass. Hai lớp này cùng có một phương thức tên là hienThi() với nội dung phương thức khác nhau và cùng có một biến number với giá trị biến khác nhau. Trong lớp Subclass chúng ta sẽ tiến hành gọi đến phương thức hienThi() và thuộc tính number của 2 lớp này. Đối với thuộc tính và phương thức của lớp Superclass, chúng ta sẽ gọi thông qua từ khóa super với 2 dòng code là super.hienThi()super.number, còn đối với thuộc tính và phương thức của lớp Subclass thì chúng ta gọi bình thường thông qua tên đối tượng của nó.

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:

Cú pháp
super(tên_đối_số);

Lưu ý: từ khóa super trong trường hợp này chỉ có thể được dùng ngay trong hàm tạo và phải được khai báo đầu tiên bên trong hàm tạo đó, nếu chúng ta để nó vào trong các phương thức bình thường khác thì hệ thống sẽ báo lỗi.

Dưới đây là ví dụ minh họa cách sử dụng từ khóa super trong trường hợp này.

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);
	}
}

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ả sau khi biên dịch chương trình:

ketqua vi du tu khoa super 2 PNG

3. Lời kết

Trong bài này, chúng ta đã tìm hiểu về tính kế thừa trong Java. Sang bài sau, chúng ta sẽ tìm hiểu về tính chất tiếp theo trong lập trình hướng đối tượng đó là tính đa hình. Các bạn theo dõi nhé!

Câu hỏi thường gặp liên quan:

Cùng chuyên mục:

Hướng dẫn Upload file với Spring Boot và jQuery Ajax trong Java

Hướng dẫn Upload file với Spring Boot và jQuery Ajax trong Java

Hướng dẫn download file với Spring Boot trong Java

Hướng dẫn download file với Spring Boot trong Java

Hướng dẫn Upload file với Spring Boot trong Java

Hướng dẫn Upload file với Spring Boot trong Java

Hướng dẫn CRUD với Spring Boot, REST và AngularJS trong Java

Hướng dẫn CRUD với Spring Boot, REST và AngularJS trong Java

Cách sử dụng Spring  Scheduled trong Spring Boot

Cách sử dụng Spring Scheduled trong Spring Boot

Cách dùng Groovy trong Spring Boot Java

Cách dùng Groovy trong Spring Boot Java

Cách dùng Spring Boot và Mustache trong Java

Cách dùng Spring Boot và Mustache trong Java

Cách dùng Spring Boot và MongoDB trong Java

Cách dùng Spring Boot và MongoDB trong Java

Cách tạo Restful Client bằng RestTemplate trong Spring Boot

Cách tạo Restful Client bằng RestTemplate trong Spring Boot

Hướng dẫn sử dụng Interceptor trong Spring Boot

Hướng dẫn sử dụng Interceptor trong Spring Boot

Sử dụng Twitter Bootstrap trong Spring Boot

Sử dụng Twitter Bootstrap trong Spring Boot

Tạo trang web đa ngôn ngữ với Spring Boot trong Java

Tạo trang web đa ngôn ngữ với Spring Boot trong Java

Tạo ứng dụng Chat với Spring Boot và Websocket

Tạo ứng dụng Chat với Spring Boot và Websocket

Sử dụng JUnit để tạo unit test trong Spring Boot

Sử dụng JUnit để tạo unit test trong Spring Boot

Cách triển khai Spring Boot trên Tomcat Server

Cách triển khai Spring Boot trên Tomcat Server

Cách test RESTful API trong Spring Boot

Cách test RESTful API trong Spring Boot

Cách dùng Spring Security trong Spring Boot để xác thực và phân quyền

Cách dùng Spring Security trong Spring Boot để xác thực và phân quyền

Duyệt cây nhị phân bằng phương pháp inOder trong Java

Duyệt cây nhị phân bằng phương pháp inOder trong Java

Xóa node của cây nhị phân tìm kiếm trong Java

Xóa node của cây nhị phân tìm kiếm trong Java

Bảo mật Spring Boot RESTful Service sử dụng Basic Authentication trong Java

Bảo mật Spring Boot RESTful Service sử dụng Basic Authentication trong Java

Top