11
LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
VỚI JAVA
Nguyễn Thị Thu Trang
[email protected]
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
Bé m«n C«ng nghÖ phÇn mÒm
Bài 8. Kế thừa (Inheritance)
2© Nguyễn Thị Thu Trang, SE-FIT-HUT
Mục tiêu của bài học
Sau khi kết thúc bài học, sinh viên có thể:
 Mô tả các khái niệm cơ bản liên quan đến kế
thừa
 Giải thích nguyên lý kế thừa
 Chỉ ra thứ tự khởi tạo và hủy bỏ đối tượng 
trong kế thừa
 Trình bày nguyên lý định nghĩa lại trong kế
thừa
 Sử dụng các vấn đề trên với ngôn ngữ lập 
trình Java.
3© Nguyễn Thị Thu Trang, SE-FIT-HUT
Bài 8. Kế thừa (Inheritance)
1. Tổng quan về kế thừa
2. Nguyên lý kế thừa
3. Khởi tạo và hủy đối tượng
4. Định nghĩa lại
5. Lớp ảo và giao diện
4© Nguyễn Thị Thu Trang, SE-FIT-HUT
Bài 8. Kế thừa (Inheritance)
1. Tổng quan về kế thừa
2. Nguyên lý kế thừa
3. Khởi tạo và hủy đối tượng
4. Định nghĩa lại
5. Lớp ảo và giao diện
25© Nguyễn Thị Thu Trang, SE-FIT-HUT
1. Tổng quan về kế thừa
Ví dụ:
 Điểm
Tứ giác gồm 4 điểm 
Æ Kết tập
 Tứ giác
Hình vuông
Æ Kế thừa
6© Nguyễn Thị Thu Trang, SE-FIT-HUT
1.1. Bản chất
Kế thừa (Inherit, Derive)
 Tái sử dụng mã nguồn (Reusability)
Tạo lớp mới bằng cách phát triển lớp đã có.
Lớp mới kế thừa những gì đã có trong lớp cũ và
phát triển những tính năng mới.
 Lớp cũ:
Lớp cha (parent, superclass)
Lớp cơ sở (base class)
 Lớp mới:
Lớp con (child, subclass)
Lớp dẫn xuất (derived class)
Tứ giác
Hình 
vuông
Hình 
thang
7© Nguyễn Thị Thu Trang, SE-FIT-HUT
1.1. Bản chất (tiếp)
Kế thừa (tiếp)
 Lớp con mở rộng (extend) từ lớp cha
Là một loại của lớp cha
Kế thừa được các thành phần dữ liệu và các hành 
vi của lớp cha
Chi tiết hóa cho phù hợp với mục đích sử dụng mới
 Thêm các thuộc tính/hành vi mới
 Chỉnh sửa lại các hành vi kế thừa từ lớp cha.
8© Nguyễn Thị Thu Trang, SE-FIT-HUT
1.2. Phân biệt kế thừa và kết tập
Kết tập tái sử dụng
thông qua lại đối tượng.
 Tạo ra tham chiếu đến 
các đối tượng của các 
lớp có sẵn trong lớp mới
Quan hệ “là một phần”
(“is a part of”)
Ví dụ: Ô tô có 4 bánh xe 
Kế thừa tái sử dụng
thông qua lớp.
 Tạo lớp mới bằng cách 
phát triển lớp đã có sẵn
Quan hệ “là một loại”
(“is a kind of”)
Ví dụ: Ô tô là một loại 
phương tiện vận tải
Kế thừa Kết tập
39© Nguyễn Thị Thu Trang, SE-FIT-HUT
1.3. Cây phân cấp kế thừa
Cây phân cấp kế thừa (Inheritance 
hierarchy)
 Cấu trúc phân cấp hình cây, biểu diễn mối 
quan hệ kế thừa giữa các lớp.
 Dẫn xuất trực tiếp
B dẫn xuất trực tiếp từ A 
 Dẫn xuất gián tiếp
C dẫn xuất gián tiếp từ A
A
B
C
10© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ về cây phân cấp kế thừa
Hình
Hình hai chiều Hình ba chiều
Hình tròn Tứ giác Tam giác Hình cầu Hình lăng trụ Tứ diện
11© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ về cây phân cấp kế thừa
Mọi đối tượng 
đều thừa kế từ
lớp gốc Object
12© Nguyễn Thị Thu Trang, SE-FIT-HUT
Bài 8. Kế thừa
1. Tổng quan về kế thừa
2. Nguyên lý kế thừa
3. Khởi tạo và hủy đối tượng
4. Định nghĩa lại
5. Lớp ảo và giao diện
413© Nguyễn Thị Thu Trang, SE-FIT-HUT
2. Nguyên lý kế thừa
Thành viên protected trong lớp cha
 Là mức truy cập ở giữa public và private
 Được truy cập ở:
Các thành viên lớp cha
Các thành viên lớp con
Các thành viên các lớp cùng thuộc 1 gói (package)
Lớp con có thể kế thừa được gì?
 Kế thừa được các thành viên (bao gồm dữ liệu và 
phương thức) được khai báo là public và protected 
của lớp cha.
 Không kế thừa được các thành viên private.
14© Nguyễn Thị Thu Trang, SE-FIT-HUT
2. Nguyên lý kế thừa (2)
Khác gói, 
non-inher
Lớp con 
cùng gói
Không có
Lớp con 
khác gói
Cùng lớp
privateprotectedpublic
15© Nguyễn Thị Thu Trang, SE-FIT-HUT
2. Nguyên lý kế thừa (2)
NoNoNoYesKhác gói, 
non-inher
NoYesYesYesLớp con 
cùng gói
No
Yes
Không có
NoYesYesLớp con 
khác gói
YesYesYesCùng lớp
privateprotectedpublic
16© Nguyễn Thị Thu Trang, SE-FIT-HUT
2. Nguyên lý kế thừa (3)
517© Nguyễn Thị Thu Trang, SE-FIT-HUT
2.1. Cú pháp kế thừa trên Java
Cú pháp kế thừa trên Java: 
 extends 
Ví dụ:
 class HinhVuong extends TuGiac 
 class Bird extends Animal
18© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 1
public class TuGiac {
protected Diem d1, d2, d3, d4;
public void setD1(Diem _d1) {d1=_d1;} 
public Diem getD1(){return d1;}
public void draw(){//Vẽ tứ giác}
…
}
public class HinhVuong extends TuGiac {
public HinhVuong(){
d1 = new Diem(0,0); d2 = new Diem(0,1);
d3 = new Diem(1,0); d4 = new Diem(1,1);
}
}
public class Test{
public static void main(String args[]){
HinhVuong hv = new HinhVuong();
hv.draw();
}
}
Sử dụng các biến 
protected trong lớp con
Gọi hàm public lớp cha 
của đối tượng lớp con
19© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 2
class Person {
private String name;
private Date bithday;
public String getName() { return name; }
...
}
class Employee extends Person {
private double salary;
public boolean setSalary(double sal) {
salary = sal;
return true;
}
public String getDetail(){
String s = name+“,”+birthday+“,”+salary;//Loi
}
}
20© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 2 – sửa lại
class Person {
protected String name;
protected Date bithday;
public String getName() { return name; }
...
}
class Employee extends Person {
private double salary;
public boolean setSalary(double sal) {
salary = sal;
return true;
}
public String getDetail(){
String s = name+“,”+birthday+“,”+salary;
}
}
621© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 2 (tiếp)
public class Test{
public static void main(String args[]){ 
Employee e = new Employee();
e.setName("John");
e.setSalary(3.0);
}
}
22© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 3 – Cùng gói
public class Person {
Date birthday;
String name;
...
}
public class Employee extends Person {
...
public String getDetail() {
String s;
String s = name + "," + birthday;
s += ",“ + salary;
return s;
}
}
23© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 3 – Khác gói
package abc;
public class Person {
protected Date birthday;
protected String name;
...
}
import abc.Person;
public class Employee extends Person {
...
public String getDetail() {
String s;
s = name + "," + birthday + "," + salary;
return s;
}
}
24© Nguyễn Thị Thu Trang, SE-FIT-HUT
2.2. Các hàm không được phép kế thừa
Các hàm không được phép kế thừa:
 Các hàm thiết lập và hàm hủy
Làm nhiệm vụ khởi đầu 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ư hàm thiết lập
725© Nguyễn Thị Thu Trang, SE-FIT-HUT
Bài 8. Kế thừa
1. Tổng quan về kế thừa
2. Nguyên lý kế thừa
3. Khởi tạo và hủy đối tượng
4. Định nghĩa lại
5. Lớp ảo và giao diện
26© Nguyễn Thị Thu Trang, SE-FIT-HUT
3. Khởi tạo và huỷ bỏ đối tượng
Khởi tạo đối tượng:
 Lớp cha được khởi tạo trước lớp con.
 Các hàm khởi tạo của lớp con gọi hàm khởi tạo của 
lớp cha
Không tường minh (implicit - tự động gọi)
Tường minh (explicit - gọi trực tiếp).
Hủy bỏ đối tượng:
 Ngược lại so với khởi tạo đối tượng
27© Nguyễn Thị Thu Trang, SE-FIT-HUT
3.1. Tự động gọi hàm khởi tạo lớp cha
Hàm khởi tạo của lớp con tự động gọi hàm khởi 
tạo mặc định của lớp cha (dòng đầu tiên trong 
hàm khởi tạo).
 Hàm khởi tạo mặc định:
Không tham số
Do hệ thống tự cung cấp (nếu không được viết lại) hoặc do 
người dùng viết lại.
 Nếu lớp cha có hàm khởi tạo mặc định thì hàm khởi 
tạo này sẽ được tự động gọi trong câu lệnh đầu tiên 
của hàm khởi tạo lớp con.
28© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ
public class TuGiac {
protected Diem d1, d2;
protected Diem d3, d4;
public TuGiac(){
System.out.println("Lop 
cha TuGiac()");
}
//…
}
public 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();
}
}
829© Nguyễn Thị Thu Trang, SE-FIT-HUT
3.2. Gọi trực tiếp hàm khởi tạo của lớp cha
Nếu lớp cha không có hàm khởi tạo mặc định 
tức là đã ghi chồng hàm khởi tạo của lớp cha 
với một số tham số thì
 Câu lệnh đầu tiên trong hàm khởi tạo của lớp con 
bắt buộc phải gọi hàm khởi tạo của lớp cha
super(Danh sách tham số);
 Hàm khởi tạo của lớp con không bắt buộc phải có
tham số.
30© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ
public class TuGiac {
protected Diem d1, d2;
protected Diem d3, d4;
public TuGiac(Diem _d1, Diem _d2, 
Diem _d3, Diem _d4){
System.out.println("Lop cha 
TuGiac(d1, d2, d3, d4)");
d1=_d1; d2=_d2;
d3=_d3; d4=_d4;
} //…
}
public class HinhVuong extends 
TuGiac {
public HinhVuong(){
System.out.println("Lop con 
HinhVuong()");
}
}
public class Test {
public static void 
main(String arg[])
{
HinhVuong hv = new 
HinhVuong();
}
}
Lỗi
31© Nguyễn Thị Thu Trang, SE-FIT-HUT
Gọi trực tiếp hàm khởi tạo của lớp cha 
Hàm khởi tạo lớp con không tham số
public class TuGiac {
protected Diem d1, d2;
protected Diem d3, d4;
public TuGiac(Diem _d1, Diem _d2, Diem 
_d3, Diem _d4){
System.out.println("Lop cha 
TuGiac(d1, d2, d3, d4)");
d1=_d1; d2=_d2;
d3=_d3; d4=_d4;
} //…
}
public class HinhVuong extends TuGiac{
public HinhVuong(){
super(new Diem(0,0),new Diem(0,1),
new Diem(1,1),new Diem(1,0));
System.out.println("Lop con 
HinhVuong()");
}
}
HinhVuong hv = new 
HinhVuong();
32© Nguyễn Thị Thu Trang, SE-FIT-HUT
Gọi trực tiếp hàm khởi tạo của lớp cha 
Hàm khởi tạo lớp con có tham số
public class TuGiac {
protected Diem d1, d2;
protected Diem d3, d4;
public TuGiac(Diem _d1, Diem _d2, 
Diem _d3, Diem _d4){
System.out.println("Lop cha 
TuGiac(d1, d2, d3, d4)");
d1=_d1; d2=_d2;
d3=_d3; d4=_d4;
} //…
}
public class HinhVuong extends TuGiac{
public HinhVuong(Diem _d1, Diem _d2, 
Diem _d3, Diem _d4){
super(_d1, _d2, _d3, _d4);
System.out.println("Lop con 
HinhVuong(d1, d2, d3, d4)");
}
}
HinhVuong hv = new 
HinhVuong(new Diem(0,0), 
new Diem(0,1), 
new Diem(1,1), 
new Diem(1,0));
933© Nguyễn Thị Thu Trang, SE-FIT-HUT
Bài 8. Kế thừa
1. Tổng quan về kế thừa
2. Nguyên lý kế thừa
3. Khởi tạo và hủy đối tượng
4. Định nghĩa lại
5. Lớp ảo và giao diện
34© Nguyễn Thị Thu Trang, SE-FIT-HUT
4. Định nghĩa lại hay ghi đè
Lớp con có thể định nghĩa hàm trùng tên với 
hàm trong lớp cha:
 Nếu hàm mới chỉ trùng tên và khác chữ ký (số 
lượng hay kiểu dữ liệu của đối số)
Æ Chồng hàm (Overloading)
 Nếu hàm mới hoàn toàn giống về giao diện (chữ
ký) với hàm trong lớp cơ sở: 
Æ Định nghĩa lại hoặc ghi đè (redefining or 
override)
35© Nguyễn Thị Thu Trang, SE-FIT-HUT
4. Định nghĩa lại hay ghi đè (2)
Phương thức override sẽ thay thế hoặc làm rõ 
hơn cho phương thức cùng tên trong lớp cha
Đối tượng của lớp dẫn xuất sẽ hoạt động với 
phương thức mới phù hợp với nó
Có tái sử dụng phương thức cùng tên của lớp 
cơ sở bằng từ khóa super
36© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ
package abc;
public class Person {
protected Date birthday;
protected String name; p g ;
public String getDetail() {...}
...
}
import abc;
public class Employee extends Person {
...
public String getDetail() {
String s = super.getDetail() + "," + salary;
return s;
}
}
10
37© Nguyễn Thị Thu Trang, SE-FIT-HUT
4. Định nghĩa lại hay ghi đè (3)
Một số quy định
 Danh sách tham số phải giống hệt phương 
thức trong lớp cha.
 Phải có cùng kiểu trả về với phương thức kế
thừa
38© Nguyễn Thị Thu Trang, SE-FIT-HUT
4. Định nghĩa lại hay ghi đè (3)
Một số quy định (tiếp)
 Các chỉ định truy cập không giới hạn chặt hơn 
phương thức trong lớp cha
Ví dụ, nếu ghi đè một phương thức protected, thì 
phương thức mới có thể là protected hoặc public, 
mà không được là private.
 Không được phép ghi đè:
Các hàm không được phép thay đổi (final hoặc 
const)
Lớp cha là final class
39© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ
class Parent {
public void doSomething() {}
private int doSomething2() {
return 0;
}
}
class Child extends Parent {
protected void doSomething() {}
private void doSomething2() {}
}
40© Nguyễn Thị Thu Trang, SE-FIT-HUT
Bài 8. Kế thừa
1. Tổng quan về kế thừa
2. Nguyên lý kế thừa
3. Khởi tạo và hủy đối tượng
4. Định nghĩa lại
5. Lớp ảo và giao diện
11
41© Nguyễn Thị Thu Trang, SE-FIT-HUT
5.1. Lớp trừu tượng (Abstract Class)
Không thể thể hiện hóa (instantiate – tạo đối 
tượng của lớp)
Chưa đầy đủ, thường được sử dụng làm lớp cha. 
Lớp con kế thừa nó sẽ hoàn thiện nốt.
Để trở thành một lớp trừu tượng, cần:
 Khai báo với từ khóa abstract
 Chứa ít nhất một phương thức trừu tượng (abstract 
method - chỉ có chữ ký mà không có cài đặt cụ thể)
public abstract void draw();
 Lớp con khi kế thừa cần cài đặt cụ thể cho các phương 
thức trừu tượng.
42© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ:
abstract class Learner {
public abstract String getName();
public abstract int getAge();
public int getMaxGrade() {
return getAge() - 5;
}
}
Nếu một lớp có một hay nhiều phương thức trừu 
tượng thì nó là lớp trừu tượng và phải được 
khai báo abstract
Lớp trừu tượng được dùng để gắn kết các lớp 
đã cài đặt đầy đủ.
5.1. Lớp trừu tượng (tiếp)
43© Nguyễn Thị Thu Trang, SE-FIT-HUT
5.2. Giao diện (Interface)
Đa kế thừa (Multiple Inheritance)
 Một lớp có thể kế thừa nhiều lớp khác 
(lớp con có thể có nhiều lớp cha)
 C++ hỗ trợ đa kế thừa
Đơn kế thừa (Single Inheritance)
 Một lớp chỉ được kế thừa từ một lớp 
khác (lớp con chỉ có một lớp cha).
 Java chỉ hỗ trợ đơn kế thừa 
Æ Đưa thêm khái niệm Giao diện 
(Interface)
A B C
D
B
A
DC
E F
44© Nguyễn Thị Thu Trang, SE-FIT-HUT
5.2. Giao diện (tiếp)
Cho phép một lớp có thể kế thừa (thực thi -
implement) nhiều giao diện một lúc.
Không thể thể hiện hóa (instantiate) trực tiếp
Để trở thành giao diện, cần
 Sử dụng từ khóa interface để định nghĩa
 Chỉ được bao gồm: 
Chữ ký các phương thức (method signature) 
Các khai báo hằng (static & final).
 Lớp thực thi giao diện 
Hoặc là lớp trừu tượng (abstract class) 
Hoặc là bắt buộc phải thực thi toàn bộ các phương thức trong 
giao diện.
12
45© Nguyễn Thị Thu Trang, SE-FIT-HUT
5.2. Giao diện (tiếp)
Cú pháp thực thi trên Java:
 extends implements <Danh 
sách giao diện>
 extends 
Ví dụ:
 public interface DoiXung {…}
public class HinhVuong extends TuGiac 
implements DoiXung {…}
 public interface FlyableThing {…}
public class Bird extends Animal 
implements FlyableThing {…}
46© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 1
public interface DoiXung {
abstract 
…
}
public abstract class TuGiac {
protected Diem p1, p2, p3, p4;
…
}
public class HinhVuong extends TuGiac 
implements DoiXung {
…
}
47© Nguyễn Thị Thu Trang, SE-FIT-HUT
Ví dụ 2
abstract class TuGiac {
protected Diem d1, d2;
protected Diem d3, d4;
// Phương thức final
public final void draw(){
//Vẽ tứ giác
}
// Phương thức trừu tượng
public abstract double 
getArea();
}
class HinhVuong extends 
TuGiac {
//Truy cập được các thành phần //dữ liệu d1, d2, d3, d4
public double area (){
// Tính diện tích hình vuông
}
public final void draw(){
// Vẽ hình vuông Æ Báo lỗi
}
}
48© Nguyễn Thị Thu Trang, SE-FIT-HUT
Kết luận
Kế thừa là một phương pháp để tái sử dụng mã 
nguồn
Kế thừa dùng khi ta có quan hệ “là một loại - is a 
kind of”.
Lớp con kế thừa toàn bộ tính năng của lớp cha và
có thể phát triển thêm các tính năng mới.
Trong Java, không hỗ trợ đa kế thừa Æ Đưa ra 
khái niệm Giao diện (Interface) cho phép lớp con 
có thể thực thi nhiều giao diện một lúc.
Hàm khởi tạo lớp con có thể gọi hàm khởi tạo lớp 
cha tường minh hoặc không tường minh.
Lớp con có thể định nghĩa lại hay ghi đè các 
phương thức đã định nghĩa trong lớp cha.
13
49© Nguyễn Thị Thu Trang, SE-FIT-HUT
Câu hỏi
Kế thừa là gì? So sánh kế thừa với kết tập?
Nêu bản chất của nguyên lý kế thừa?
Những hàm nào không được phép kế thừa và tại 
sao?
So sánh lớp trừu tượng và giao diện?
Nêu nguyên lý và thứ tự thực hiện của hàm khởi 
tạo trong kế thừa?