Chương 3 Lập trình Hướng đối tượng với Java (tt)
Ầ
TR N MINH THÁI Email: minhthai@huflit.edu.vn Website: www.minhthai.edu.vn
Cập nhật: 22 tháng 03 năm 2017
Nội dung
1. Vấn đề tái sử dụng code
2. Kế thừa trong Java
3. Tính đa hình trong Java
4. Cài đặt interface trong Java
5.
Lập trình tổng quát
#2
VẤN ĐỀ TÁI SỬ DỤNG CODE
Tái sử dụng code
• Lập trình cấu trúc: chương trình con
• OOP: nhiều loại đối tượng có thuộc tính, hành vi tương tự nhau
tái sử dụng các lớp đã viết
• Trong một lớp vẫn tái sử dụng phương thức
• Ưu điểm:
#4
• Giảm chi phí
• Nâng cao khả năng bảo trì và khả năng mô hình hóa
Các hình thức tái sử dụng code
1.
Sao chép lớp cũ thành 1 lớp khác Hạn chế: Dư thừa, khó quản lý khi có thay đổi
2.
Kết hợp: Lớp mới là tập hợp/ sử dụng các lớp đã có
3.
Kế thừa: Lớp mới phát triển thêm các thuộc tính hoặc phương thức từ lớp đã có
#5
KẾT HỢP AGGREGATION
Kết hợp (Aggregation)
• Thể hiện mối quan hệ “has-a”: Lớp mới chứa các đối tượng
của lớp cũ
#7
• Lớp mới: Lớp chứa/ Lớp toàn thể
• Ví dụ:
• Lớp cũ: Lớp thành phần
• Lớp cũ: Điểm (Point)
• Lớp mới: Tam giác (Triangle) có 3 điểm
Lớp chứa tái sử dụng các thành viên của lớp thành phần thông qua đối tượng
Sơ đồ lớp
#8
Số lượng thành phần
• 1 số nguyên dương (1, 2, 3...)
• Dải số (0..1, 1..n)
ấ ỳ
ị
• B t k giá tr nào: *
• Không ghi: 1
Ví dụ Lớp ToaDoDiem
#9
package minhthai.oop.thietkelop; public class ToaDoDiem { private int x; private int y; public ToaDoDiem() { this.setX(0); this.setY(0); } public ToaDoDiem(int x, int y) { this.setX(x); this.setY(y); } public int getX() {return x;} public void setX(int x) {this.x = x;} public int getY() {return y;} public void setY(int y) {this.y = y;} public void hienThi() { System.out.printf("(%d, %d)\n", this.x, this.y); } }
Ví dụ Lớp TamGiac
Nếu lớp thành phần khác package thì dùng lệnh import
#10
Ví dụ Lớp TamGiac …
#11
Bài tập 1
Xây dựng một trò chơi xúc xắc. Cách chơi như sau:
• Mỗi hạt xúc xắc được gieo sẽ có giá trị ngẫu nhiên 1...6
• Hai người lần lượt gieo 1 hạt xúc xắc
• Sau mỗi lượt gieo, số điểm của lượt đó được tích lũy vào số
điểm của người chơi
• Sau các lượt gieo theo quy định, người thắng cuộc là người có
tổng số điểm lớn hơn
Hãy xác định các lớp cần thiết và cài đặt
#12
Xác định lớp
• Xúc xắc (XucXac)
#13
• Fields: giá trị của mặt (giaTri)
• Người chơi (NguoiChoi)
• Methods: sinh ngẫu nhiên giá trị mặt của xúc xắc (sinhGiaTri())
• Fields: tên (ten), điểm (diem)
• Methods: gieo xúc xắc (gieoXucXac())
Xác định lớp
• Trận đấu (TranDau)
#14
• Fields: xúc xắc (xucXac), 2 người chơi (nguoiChoi), số vòng chơi
(soVong), người thắng cuộc (nguoiThang)
(hienThi()), thực hiện trận đấu (thucHienTranDau())
• Methods: bắt đầu (batDau()), kết thúc (ketThuc), hiển thị thông tin
Xác định lớp
#15
Lớp XucXac
#16
public class XucXac { private int giaTri;
public int getGiaTri() { return giaTri; } public void setGiaTri(int giaTri) { this.giaTri = giaTri; } public XucXac(){ giaTri=1; } public void sinhGiaTri(){ Random random = new Random(); this.giaTri=random.nextInt(5) + 1; } }
Lớp NguoiChoi
#17
public class NguoiChoi { private String ten; private int diem; public String getTen() { return ten; } public void setTen(String ten) { this.ten = ten; } public int getDiem() { return diem; } public void setDiem(int diem) { this.diem = diem; }
Lớp NguoiChoi
#18
public NguoiChoi(String ten){ this.ten=ten; this.diem=0; } public void gieoXucXac(XucXac xucXac){ Scanner sn = new Scanner(System.in); System.out.print(">>> Hay nhan Enter
de gieo xuc xac...");
sn.nextLine(); xucXac.sinhGiaTri(); this.diem+=xucXac.getGiaTri(); System.out.println("-- Diem: "
+ this.diem);
} }
Lớp TranDau
#19
public class TranDau { private XucXac xucXac; private NguoiChoi nguoiChoi1; private NguoiChoi nguoiChoi2; private NguoiChoi nguoiThang; private int soVong;
public TranDau(String ten1, String ten2,
int soVong){
this.nguoiChoi1 = new NguoiChoi(ten1); this.nguoiChoi2 = new NguoiChoi(ten2); this.xucXac = new XucXac(); this.soVong = soVong; }
Lớp TranDau
#20
public void batDau(){ System.out.println("Tran dau bat dau..."); for(int i=1; i<=this.soVong; i++){ System.out.printf("***** Vong %d *****\n",i); System.out.println(">" + nguoiChoi1.getTen()
+ " gieo xuc xac");
nguoiChoi1.gieoXucXac(xucXac);
System.out.println(">" + nguoiChoi2.getTen()
+ " gieo xuc xac");
nguoiChoi2.gieoXucXac(xucXac);
} }
Lớp TranDau
#21
public void ketThuc(){ int diem1= nguoiChoi1.getDiem(); int diem2=nguoiChoi2.getDiem(); if(diem1>diem2) this.nguoiThang=this.nguoiChoi1; else if(diem2>diem1) this.nguoiThang=this.nguoiChoi2; }
Lớp TranDau
#22
public void hienThi(){ System.out.println("* Ket qua tran dau *"); System.out.printf("- Diem cua %s: %d",
nguoiChoi1.getTen(), nguoiChoi1.getDiem());
System.out.printf("- Diem cua %s: %d",
nguoiChoi2.getTen(), nguoiChoi2.getDiem());
if(nguoiThang!=null)
System.out.printf("Nguoi thang cuoc: %s",
nguoiThang.getTen());
else
System.out.println("Tran dau hoa!!!");
} public void thucHienTranDau(){ batDau(); ketThuc(); hienThi(); } }
#23
public class XucXacTest { public static void main(String []args){ String ten1, ten2; int soVong; Scanner sn = new Scanner(System.in);
System.out.print("> Ten nguoi choi 1: "); ten1=sn.nextLine(); System.out.print("> Ten nguoi choi 2: "); ten2=sn.nextLine(); System.out.print("> So vong dau: "); soVong=sn.nextInt();
TranDau tranDau = new
TranDau(ten1, ten2, soVong);
tranDau.thucHienTranDau(); } }
Bài tập 2
Hãy viết lại các lớp trong Bài tập 1 để thoả yêu cầu sau:
• Có thêm thuộc tính soBanThang ghi lại số bàn thắng
• Cho biết số ván đấu (>2), nếu người chơi nào thắng quá bán
đầu tiên thì sẽ thắng
• VD: Giả sử 2 người chơi phải chơi 3 ván đấu. Nếu người chơi
nào thắng trước 2 ván thì người chơi đó thắng cả trận đấu
• Nếu hòa thì tính điểm để kết luận người thắng
#24
GOM NHÓM ĐỐI TƯỢNG
Vấn đề gom nhóm đối tượng
• Nhóm các đối tượng có cùng tập thuộc tính/ hành vi lại với nhau
thành một lớp
• Nhóm các đối tượng có cùng một số thuộc tính/ hành vi
VD: nhóm tất cả xe chạy bằng động cơ thành một nhóm, rồi phân thành các nhóm nhỏ hơn tuỳ theo loại xe (xe gắn máy, xe ô tô, xe tải, ...)
#26
Vấn đề gom nhóm đối tượng
• Mỗi nhóm con là một lớp các đối tượng tương tự có chung một
số đặc điểm
• Quan hệ giữa các nhóm con với nhóm lớn được gọi là quan hệ
“is-a”
#27
Vấn đề gom nhóm đối tượng
• Ví dụ:
o Một xe ô tô “is-a” xe động cơ
o Một xe tải “is-a” xe động cơ
o Một xe máy “is-a” xe động cơ
#28
Vấn đề gom nhóm đối tượng
• Mối liên kết giữa các lớp trong quan hệ “is-a” xuất phát từ thực tế:
#29
• Các lớp con có mọi thuộc tính/ hành vi của lớp cha
Quan hệ “is-a” còn gọi là sự thừa kế
• và cộng thêm các thuộc tính/ hành vi khác
THỪA KẾ INHERITANCE
Mục tiêu của thừa kế
Tạo lớp mới bằng cách phát triển từ lớp đã có
• Lớp mới kế thừa những thành viên đã có trong lớp cũ
• Lớp cũ: Lớp cha (superclass), lớp cơ sở (baseclass)
• Lớp mới: Lớp con (subclass), lớp dẫn xuất (derived class)
#31
Mục tiêu của thừa kế
Ví dụ:
#32
• Lớp cũ: Điểm (ToaDoDiem)
• Kết hợp: Tam giác (TamGiac) có 3 điểm
• Kế thừa: Tam giác vuông (TamGiacVuong)
Sơ đồ thừa kế của lớp
#33
Lớp cơ sở
• Lớp cha – superclass (hoặc lớp cơ sở - base class)
#34
• Lớp tổng quát hơn trong mối quan hệ “is-a”
• Các đối tượng thuộc lớp cha có cùng tập thuộc tính và hành vi
Lớp dẫn xuất
• Lớp con – subclass (hoặc lớp dẫn xuất – derived class)
#35
• Lớp cụ thể hơn trong một quan hệ “is-a”
kế từ lớp cha), kèm thêm tập thuộc tính và hành vi của riêng lớp con
• Các đối tượng thuộc lớp con có cùng tập thuộc tính và hành vi (do thừa
Lớp cơ sở - lớp dẫn xuất
Kế thừa phần lớn các thành viên dữ liệu và phương thức của lớp cơ sở
(ngoại trừ constructor, destructor)
Lớp dẫn xuất
Có thể bổ sung thêm các thành viên dữ liệu mới và các phương thức mới
Lớp cơ sở trực tiếp
Class A
Lớp cơ sở
Class B
Lớp cơ sở gián tiếp
Class C
#36
Phân loại thừa kế
1.
Thừa kế đơn (single inheritance): chỉ có một lớp cha
2.
Đa thừa kế (multiple inheritance): có nhiều lớp cha
#37
Sơ đồ quan hệ đối tượng (Object Relationship Diagram – ORD)
• Sự khác nhau giữa lớp cơ sở và lớp dẫn xuất
• Sự khác nhau giữa các
lớp dẫn xuất
#38
Nguyên tắc biểu diễn sơ đồ thừa kế
Các quan hệ thừa kế luôn được biểu diễn với các lớp dẫn xuất đặt dưới lớp cơ sở để nhấn mạnh bản chất phả hệ của quan hệ
#39
Ưu điểm của thừa kế
1.
Tiết kiệm thời gian và công sức
2.
Tái sử dụng lại những lớp có sẵn
3. Giảm lượng code phải thiết kế, viết, kiểm tra
4.
Tránh trùng lắp code
5.
Rút ngắn thời gian giúp LTV tập trung vào mục tiêu
6. Giúp phân loại và thiết kế lớp dễ dàng, dễ quản lý
#40
Kết hợp vs Kế thừa
Th a kừ ế
ế ợ K t h p
ử ụ
ử ụ
ồ
ồ Tái s d ng mã ngu n
Tái s d ng mã ngu n
ố ượ
thông qua l pớ
thông qua đ i t
ng
Quan h “ệ isa”
Quan h “ệ hasa”
ụ
ụ
Ví d : Tam giác vuông
Ví d : Tam giác
là
có 3 đ nhỉ
#41
ộ ạ tam giác
m t lo i
ĐỊNH NGHĨA LỚP THỪA KẾ
Định nghĩa lớp kế thừa
• Cú pháp
class SubClass extends SuperClass{
Định nghĩa SubClass
}
• Lớp con truy cập tới thành viên lớp cha qua từ khóa super
• Mọi lớp trong Java đều kế thừa từ lớp tổng quát Object
• Lớp Object cung cấp một số phương thức toString(), equals()
• Java chỉ cho phép đơn kết thừa: một lớp chỉ có thể kế thừa từ
duy nhất 1 lớp khác
#43
Chỉ định truy cập của lớp cha
• public: cho phép lớp con kế thừa ở bất kỳ đâu
• Không chỉ định: chỉ cho phép lớp con kế thừa khi cùng package
với lớp cha
#44
Chỉ định truy cập thành viên
#45
• public, protected: cho phép lớp con được kế thừa và truy cập thuộc tính/phương thức trên lớp cha (!!!đối với public không cần kế thừa cũng truy cập được)
• Không chỉ định: chỉ cho phép lớp con ở cùng package được kế thừa và được truy cập tới thuộc tính/thành viên tương ứng của lớp cha
• private: lớp con không được kế thừa thuộc tính/phương thức này, không được truy cập vào thuộc tính/thành viên tương ứng trên lớp cha
Ví dụ chỉ định public cho class cha
#46
package minhthai.oop.kethua.loppublic; public class LopCha { private int privateValue; protected int protectedValue; int noModifierValue; public int publicValue;
private void privateMethod() { } protected void protectedMethod() { } void noModifierMethod() { } public void publicMethod() { } }
Ví dụ class con cùng gói
#47
package minhthai.oop.kethua.loppublic; public class LopCon extends LopCha { public void phuongThuc() { //Sử dụng thuộc tính của lớp cha super.privateValue = 0; //Lỗi super.protectedValue = 0; //OK super.noModifierValue = 0; //OK super.publicValue = 0; //OK
//Gọi phương thức của lớp cha super.privateMethod(); //Lỗi super.protectedMethod(); //OK super.noModifierMethod(); //OK super.publicMethod(); //OK } }
Ví dụ class con khác gói
#48
package minhthai.oop.kethua.otherpack; import minhthai.oop.kethua.loppublic.*; public class LopCon extends LopCha { public void phuongThuc() { //Sử dụng thuộc tính của lớp cha super.privateValue = 0; //Lỗi super.protectedValue = 0; //OK super.noModifierValue = 0; //Lỗi super.publicValue = 0; //OK
//Gọi phương thức của lớp cha super.privateMethod(); //Lỗi super.protectedMethod(); //OK super.noModifierMethod(); //Lỗi super.publicMethod(); //OK } }
Ví dụ không chỉ định public class cha
ươ
ự ỉ
ị
• Cùng gói: t
ng t
ch đ nh public
ế ừ
• Khác gói: không cho k th a!!!
#49
KHỞI TẠO ĐỐI TƯỢNG TRONG THỪA KẾ
Khởi tạo đối tượng trong thừa kế
• Lớp con không thừa kế constructor của lớp cha
• Các constructor của lớp con tự động gọi default constructor
của lớp cha (nếu có)
• Nếu lớp cha không có default constructor thì phải gọi phương
thức khác default constructor của lớp cha
• Cú pháp: super(parameterList)
#51
Thứ tự khởi tạo và huỷ trong thừa kế
#52
A
B
!!! Lớp cha phải được gọi khởi tạo trước lớp con
C
Nếu không Error: call to super must be first statement in constructor
Ví dụ khởi tạo đối tượng trong thừa kế
#53
Ví dụ khởi tạo đối tượng trong thừa kế …
#54
Ví dụ khởi tạo đối tượng trong thừa kế …
#55
Ví dụ khởi tạo đối tượng trong thừa kế …
#56
Đối tượng cha và con
• Khi tạo đối tượng con thì đối tượng cha cũng được tạo ra độc
lập
• Đối tượng con tham chiếu tới đối tượng cha qua super (tham
chiếu này là private)
• Trong lớp con, nếu truy cập tới thành viên của lớp cha thì được thông qua super (tường minh, hoặc không tường minh): đối tượng con được xem như đối tượng thuộc lớp cha (upcasting)
#57
Upcasting và Downcasting
• Upcasting: đối tượng lớp con được nhìn nhận như đối tượng
lớp cha: Thực hiện tự động
• Downcasting: đối tượng lớp cha được nhìn nhận như đối tượng
lớp con: Phải ép kiểu
#58
Ví dụ
#59
Toán tử instanceof
• Kiểm tra một đối tượng có phải đang là thể hiện của lớp hoặc
giao diện nào đó không: true hoặc false
• Cú pháp:
objectName instanceof ClassName
objectName instanceof InterfaceName
#60
CÁC BƯỚC THIẾT KẾ LỚP THỪA KẾ
Các bước thiết kế lớp thừa kế
• B1: Xác định các lớp đối tượng trong bài toán yêu cầu
• B2: Liệt kê các thành phần thuộc tính và phương thức cho
từng lớp
• B3: Xác định những thuộc tính và phương thức chung giữa các
lớp và tạo thành lớp cơ sở cho những lớp này
• B4: Vẽ sơ đồ lớp
#62
Nhận biết kế thừa?
class AB
class A
class A
class B
class B
#63
Ví dụ
Cần quản lý thông tin của giảng viên và sinh viên trong một trường Đại học (tạo đối tượng thông qua constructor)
• Đối với sinh viên gồm các thông tin và hành vi:
#64
• Họ tên
• Tuổi
• Số tín chỉ đã tích luỹ
• Cập nhật số tín chỉ
• Hiển thị thông tin
Ví dụ (tt)
• Đối với giảng viên gồm các thông tin và hành vi:
#65
• Họ tên
• Tuổi
• Học hàm (nếu có) và học vị
• Hệ số lương
• Mức lương cơ bản
• Hiển thị thông tin
Phân tích và thiết kế lớp
• B1: Xác định lớp đối tượng
1. Lớp Sinh viên (SinhVien)
2. Lớp Giảng viên (GiangVien)
#66
Phân tích và thiết kế lớp B2: Liệt kê các thuộc tính & phương thức
#67
Lớp SinhVien
• Fields: hoTen (họ tên), tuoi (tuổi), soTinChi (số tín chỉ đã tích lũy)
thông tin sinh viên)
• Methods: capNhatTinChi (Cập nhật số tín chỉ), hienThiSV (hiển thị
Lớp GiangVien
heSoLuong (hệ số lương), luongCB (lương cơ bản)
• Fields: hoTen (họ tên), tuoi (tuổi), hocVi (học hàm và học vị),
• Methods: hienThiGV (hiển thị thông tin giảng viên)
Phân tích và thiết kế lớp B3: Xác định những thông tin chung
#68
Lớp SinhVien
• Fields: hoTen (họ tên), tuoi (tuổi), soTinChi (số tín chỉ đã tích lũy)
thông tin sinh viên)
• Methods: capNhatTinChi (Cập nhật số tín chỉ), hienThiSV (hiển thị
Lớp GiangVien
heSoLuong (hệ số lương), luongCB (lương cơ bản)
• Fields: hoTen (họ tên), tuoi (tuổi), hocVi (học hàm và học vị),
• Methods: hienThiGV (hiển thị thông tin giảng viên)
Phân tích và thiết kế lớp B3: … tách thành lớp cơ sở
Tách những thông tin chung thành 1 lớp mới: Lớp con người (ConNguoi) gồm các thông tin và hành vi chung
#69
Lớp ConNguoi
• Fields: hoTen (họ tên), tuoi (tuổi)
• Methods: hienThi (hiển thị thông tin: hoTen và tuoi)
Phân tích và thiết kế lớp B4: Sơ đồ lớp
#70
public class ConNguoi { private String hoTen; private int tuoi;
public String getHoTen() { return hoTen; } public void setHoTen(String hoTen) { this.hoTen = hoTen; } public int getTuoi() { return tuoi; } public void setTuoi(int tuoi) { this.tuoi = tuoi; }
public ConNguoi(){ this.setHoTen(""); this.setTuoi(0); } public ConNguoi(String hoTen, int tuoi) { this.setHoTen(hoTen); this.setTuoi(tuoi); } public void hienThi() { System.out.println("- Ho ten: "
+ this.getHoTen());
System.out.println("- Tuoi: "
+ this.getTuoi());
} }
public class GiangVien extends ConNguoi { private String hocVi; private double heSoLuong; private int luongCB;
public GiangVien(String hoTen, int tuoi,
String hocVi, double heSoLuong, int luongCB) {
super(hoTen, tuoi); this.setHocVi(hocVi); this.setHeSoLuong(heSoLuong); this.setHeSoLuong(luongCoBan); } public GiangVien() { this.setHocVi(""); this.setHeSoLuong(0); this.setLuongCoBan(0); }
public String getHocVi() { return hocVi; }
public void setHocVi(String hocVi) { this.hocVi = hocVi; }
public double getHeSoLuong() { return heSoLuong; }
public void setHeSoLuong(double heSoLuong) { this.heSoLuong = heSoLuong; }
public int getLuongCoBan() { return luongCoBan; } public void setLuongCoBan(int luongCoBan) { this.luongCoBan = luongCoBan; } public void hienThiGV() { super.hienThi(); System.out.println("- Hoc vi: " + this.getHocVi());
System.out.println("- He so luong: "
+ this.getHeSoLuong());
System.out.println("- Luong co ban: "
+ this.getLuongCoBan());
} }
public class SinhVien extends ConNguoi { private int soTinChi;
public int getSoTinChi() { return soTinChi; } public void setSoTinChi(int soTinChi) { this.soTinChi = soTinChi; } public SinhVien() { this.setSoTinChi(0); } public SinhVien(String hoTen, int tuoi) { super(hoTen, tuoi); this.setSoTinChi(0); }
public void capNhatTinChi(int soLuong) { this.setSoTinChi(this.getSoTinChi()
+ soLuong);
}
public void hienThiSV() { super.hienThi(); System.out.println("- So tin chi tich luy: "
+ this.getSoTinChi());
} }
public class SinhVienTest { public static void main(String []args) { System.out.println("*Tao sinh vien An:"); SinhVien sinhVien = new SinhVien("An", 17); System.out.println("*Thong tin cua An:"); sinhVien.hienThiSV();
System.out.println("*An hoc xong mon OOP"); System.out.println("*Cap nhat tin chi cho An:"); sinhVien.capNhatTinChi(4);
System.out.println("*Thong tin cua An:"); sinhVien.hienThiSV(); } }
Che thuộc tính
Trong lớp con khai báo một thuộc tính có tên giống lớp cha thì trong lớp con thuộc tính của lớp cha bị che đi
• Để truy cập tới thuộc tính trên lớp cha dùng super
• Để phân biệt trong lớp con, dùng this
#79
Ví dụ
#80
Ví dụ
#81
Phương thức cùng tên
• Nạp chồng phương thức (Overloading): giữ tên và giá trị trả về,
thay đổi đối số
• Ghi đè phương thức (Overriding): giữ nguyên tên, giá trị trả về
và đối số
#82
Phương thức thức cùng tên
• Liên kết tĩnh: Khối mã lệnh của phương thức được xác định khi
dịch
• Liên kết động: Khối mã lệnh của hàm được xác định khi
chương trình thực thi
• Liên kết lời gọi hàm: xác định địa chỉ trên bộ nhớ của khối mã
lệnh thực hiện phương thức khi có lời gọi
#83
!!!Nạp chồng phương thức: thực hiện liên kết động
Định nghĩa lại phương thức lớp cơ sở
• Lớp con có thể định nghĩa lại các phương thức kế thừa từ lớp
cha dùng kỹ thuật overriding
!!!Phương thức ở lớp cha và lớp con phải cùng nguyên mẫu
#84
Phân biệt Overriding với Overloading phương thức
public class LopCha { private int money; public LopCha() { this.money = 1000; } public void rutTien(int soTien) { this.money -= soTien; System.out.println("Tien cua cha: " + this.money);
} }
public class LopCon extends LopCha { private int money; public LopCon() { this.money = 500; } public void hienThi(){ System.out.println("Tien cua con: " + this.money); } }
public class NonOverrideTest { public static void main(String []args){ LopCon lopCon = new LopCon(); lopCon.rutTien(200); lopCon.hienThi(); } }
public class LopCha { private int money; public LopCha() { this.money = 1000; } public void rutTien(int soTien) { this.money -= soTien; System.out.println("Tien cua cha: " + this.money);
} }
public class LopCon extends LopCha { private int money; public LopCon() { this.money = 500; } public void rutTien(int soTien) { this.money -= soTien; System.out.println("Tien cua con: " +this.money); } }
public class OverrideTest { public static void main(String []args){ LopCon lopCon = new LopCon(); lopCon.rutTien(200); } }
Cấm overriding phương thức
• Đảm bảo tính đúng đắn: overrideing phương thức có thể gây ra
sự sai lạc về ý nghĩa
• Tính hiệu quả: giảm thời gian xử lý lời gọi phương thức
định nghĩa phương thức với từ khóa final
#89
Ví dụ
#90
Lỗi
Overriding equals()
• Không thể dùng toán tử so sánh == để so sánh 2 đối tượng
• Mọi lớp được kế thừa phương thức equals từ lớp Object định
nghĩa lại cho phù hợp
• Hai đối tượng bằng nhau khi thỏa mãn 2 điều kiện:
#91
• Cùng thuộc một lớp
• Giá trị của mọi thuộc tính là như nhau
!!!2 giá trị tham chiếu bằng nhau đối tượng bằng nhau
Overriding equals() cho lớp ConNguoi
#92
Overriding equals() cho lớp ConNguoi
#93
*** Dung toan tu == >>> nguoi1 != nguoi2 *** Dung phuong thuc equals >>> nguoi1 == nguoi2
TÍNH ĐA HÌNH TRONG JAVA
Tính đa hình trong Java
• Khái niệm
• Trừu tượng hoá
• Hiện thực đa hình trong Java
#95
Khái niệm Đa hình
#96
Đa hình (polymorphism)
• poly = many
ệ ượ
ố ượ
Đa hình là hi n t
ng các đ i t
ộ ng thu c các
ớ l p khác
ả nhau có kh năng hi u
ộ ể cùng m t thông đi p
ệ theo các cách
ể ồ ạ ủ
ộ ố ượ
ề
ặ
khác nhau ho c nhi u ki u t n t
i c a m t đ i t
ng
• morphism = forms
Khái niệm Đa hình
#97
LandRover object
LandRover dùng 2.0 L engine để move
Move Ford object
Ford dùng V engine để move
Honda object
Honda dùng i-vtec để move
Khái niệm Đa hình
#98
ươ
ộ
ươ
ứ : Cùng m t ph
ứ ng th c có
• Đa hình ph
ng th c
ự
ệ
ạ ố ượ
th đ
ể ượ th c hi n khác nhau
c
trên các lo i đ i t
ng
khác nhau
ố ượ
ậ
ề
ố ượ : nhìn nh n đ i t
ng theo nhi u
• Đa hình đ i t
ng
ể
ki u khác nhau
Khái niệm Đa hình
#99
Đa hình phương thức
Các lớp dẫn xuất cài đặt cùng một phương thức của lớp cơ sở, nhưng mỗi lớp dẫn xuất có cách cài đặt khác nhau overriding phương thức
Khái niệm Đa hình
#100
Phân biệt Overloading vs Overriding?
• Overloading (nạp chồng) phương thức: giữ tên và giá trị trả về,
chỉ thay đổi đối số
• Overriding (ghi đè) phương thức: giữ nguyên tên, giá trị trả về
và đối số (không thay đổi nguyên mẫu phương thức)
Khái niệm Đa hình
Muốn đa hình phương thức cho các đối tượng trong các lớp?
1.
Các lớp phải có mối quan hệ thừa kế
2.
Các phương thức đa hình phải cùng chung mẫu trong lớp cơ sở và lớp dẫn xuất (overriding)
#101
PHƯƠNG THỨC TRỪU TƯỢNG ABSTRACT METHOD
Vấn đề overriding phương thức
Kế thừa giúp khái quát hóa thông tin cụ thể của lớp đối tượng thành các thông tin chung (trừu tượng hóa đối tượng)
#103
Vấn đề overriding phương thức
• Mức độ trừu tượng hóa càng cao phương thức chung cho
các đối tượng sẽ ở mức tổng quát nhất
• Phương thức ở mức tổng quát nhất có thể không có cách hiện
thực cụ thể phương thức rỗng
• Ví dụ:
Lớp Hình chữ nhật, Hình tam giác, Hình tròn có thể trừu tượng thành Lớp Hình học nói chung
Muốn tính diện tích cho một Hình học?
#104
Vấn đề overriding phương thức
• Phương thức không cài đặt được gọi là phương thức trừu
tượng (abstract)
• Cú pháp
#105
public abstract dataType methodName(listParameter);
LỚP TRỪU TƯỢNG ABSTRACT CLASS
Lớp trừu tượng
• Khi lớp cơ sở có tồn tại phương thức abstract thì lớp đó được
gọi là lớp trừu tượng (abstract class)
• Bổ sung từ khoá abstract phía trước class
#107
public abstract class ClassName{ Khai báo thuộc tính; public abstract dataType methodName(listParameter); Định nghĩa các phương thức khác; }
Đặc điểm lớp trừu tượng
• Phương thức trừu tượng không được phép định nghĩa tại lớp
cha (kết thúc khai báo bằng dấu ;)
• Lớp con kế thừa từ lớp trừu tượng phải định nghĩa nội dung
của phương thức trừu tượng
• Chỉ định truy cập không được chặt hơn lớp cha
• Không được tạo đối tượng từ lớp trừu tượng
• Lớp trừu tượng vẫn có constructor
#108
Ví dụ
Hãy sử dụng kỹ thuật kế thừa và đa hình để viết chương trình cho phép tạo đối tượng hình tròn và hình chữ nhật. Sau đó tính và in thông tin diện tích của mỗi hình
1.
Hình tròn gồm các thông tin: Tọa độ tâm và bán kính
2.
Hình chữ nhật gồm các thông tin: Tọa độ góc trên bên trái, chiều ngang và chiều đứng
#109
Ví dụ …
#110
Xác định lớp và thông tin của lớp
• Lớp hình tròn (HinhTron):
Fields: Toạ độ tâm (x, y), bán kính (banKinh)
1.
• Lớp hình chữ nhật (HinhChuNhat):
2. Methods: Tính diện tính (tinhDienTich)
Fields: Toạ độ góc (x, y), kích thước (chieuNgang, chieuDung)
1.
2. Methods: Tính diện tích (tinhDienTich)
Ví dụ …
#111
Xác định các điểm chung của các lớp
• Lớp hình tròn (HinhTron):
Fields: Toạ độ tâm (x, y), bán kính (banKinh)
1.
• Lớp hình chữ nhật (HinhChuNhat):
2. Methods: Tính diện tính (tinhDienTich)
Fields: Toạ độ góc (x, y), kích thước (chieuNgang, chieuDung)
1.
2. Methods: Tính diện tích (tinhDienTich)
Ví dụ …
• Cần đa hình phương thức tinhDienTich()
• Tuy nhiên công thức tính diện tích chung cho cả hình tròn và
hình chữ nhật: rỗng phương thức trừu tượng
#112
public abstract double tinhDienTich();
Lớp HinhHoc phải là trừu tượng
public abstract class HinhHoc
Ví dụ …
#113
Lớp HinhHoc
#114
Lớp HinhTron
#115
Lớp HinhChuNhat
#116
Lớp HinhHocTest
#117
GIAO DIỆN INTERFACE
Giao diện
• Sử dụng trong trường hợp đa kế thừa (kế thừa từ nhiều lớp)
• Giao diện chỉ quy định các phương thức phải có, nhưng không
định nghĩa cụ thể
Tách rời đặc tả mức trừu tượng và triển khai cụ thể
Đảm bảo tính cộng tác trong phát triển phần mềm
Các giao diện có thể kế thừa nhau
#119
Giao diện
• Cú pháp
Modifier interface InterfaceName { Khai báo các hằng số Khai báo các phương thức }
#120
Triển khai giao diện
Modifier class ClassName implements
Interface1, Interface2 {
1. Định nghĩa lớp
2. Định nghĩa tất cả các phương thức
của Interface1 và Interface2
}
#121
Kế thừa và triển khai giao diện
#122
Modifier class SubClass extends SuperClass implements Interface1, Interface2 { Định nghĩa SubClass kế thừa từ SuperClass Định nghĩa tất cả phương thức của Interface1 và Interface2 }
Giao diện vs Trừu tượng
ừ ượ
Giao di nệ
Tr u t
ng
ỉ ượ
c phép có thành viên
ể
ộ
Có th có thu c tính
Ch đ h ngằ
ừ
ng th c là tr u ậ
ươ ớ
ỉ
ứ ị ng v i ch đ nh truy c p
ừ ứ ươ ng th c tr u ươ ể ng ng, có th có ph
ọ M i ph ượ t public
Ngoài ph ượ t ứ th c riêng
ươ
ở
ứ ng th c kh i
ươ
ứ
Có ph
ở ạ ng th c kh i t o
Không có ph t oạ
ỉ
ộ ớ ề
ừ ượ
ể ể M t l p có th tri n khai ệ nhi u giao di n
ộ ớ M t l p ch có th k th a ừ ộ ớ m t l p tr u t t
ể ế ừ ng
ồ
ử ụ
ồ
ử ụ Không tái s d ng mã ngu n
Có tái s d ng mã ngu n
#123
Ví dụ
#124
Giao diện HinhHoc
#125
Lớp HinhTron
#126
Lớp HinhChuNhat
#127
Lập trình tổng quát
• Xây dựng chương trình có thể làm việc với nhiều kiểu dữ liệu
khác nhau trên cùng thao tác xữ lý
#128
Cách thức lập trình tổng quát
#129
Cách thức lập trình tổng quát
#130
Bài tập
Thiết kế chương trình quản lý danh sách các hình vẽ, gồm các loại hình vẽ sau:
• Hình chữ nhật: tọa độ tâm, chiều rộng và chiều dài.
• Hình tròn: tọa độ tâm, bán kính.
• Hình tam giác: tọa độ tâm, chiều dài 3 cạnh.
Chức năng: nhập, xuất danh sách các hình, cho biết số lượng và hình có diện tích lớn nhất của từng loại.
#131
Yêu cầu: vẽ sơ đồ lớp, định nghĩa tất cả lớp với những phương thức cần thiết.
Q&A
#132

