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)
13 trang |
Chia sẻ: lylyngoc | Lượt xem: 1682 | Lượt tải: 1
Bạn đang xem nội dung tài liệu Bài 8. Kế thừa, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
11
LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
VỚI JAVA
Nguyễn Thị Thu Trang
trangntt-fit@mail.hut.edu.vn
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?