Bài giảng Lập trình hướng đối tượng - Chương 3: Lập trình hướng đối tượng với Java (phần 2) cung cấp cho người học các kiến thức: Vấn đề tái sử dụng code, kế thừa trong Java, tính đa hình trong Java, cài đặt interface trong Java, lập trình tổng quát. Mời các bạn cùng tham khảo nội dung chi tiết.
Trang 2Nộ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
Trang 3Vấn đề 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:
• Giảm chi phí
• Nâng cao khả năng bảo trì và khả năng mô hình hóa
Trang 4• 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ó
Trang 5Kết hợp (Aggregation)
• Thành phần lớp mới chứa các đối tượng của lớp cũ
• Lớp mới: Lớp chứa/Lớp toàn thể
• Lớp cũ: Lớp thành phần
• Ví dụ:
• 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 thuộc tính và phương thức của lớp thành phần thông qua đối tượng
Trang 7Ví dụ Lớp ToaDoDiem
Trang 8Ví dụ Lớp ToaDoDiem (tt)
Trang 9Ví dụ Lớp TamGiac
Trang 10Ví dụ Lớp TamGiac (tt)
Trang 11Bà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
Trang 12Xác định lớp
• Xúc xắc (XucXac)
• Thuộc tính: giá trị của mặt (giaTri)
• Phương thức: sinh ngẫu nhiên giá trị mặt của xúc xắc
(sinhGiaTri())
• Người chơi (NguoiChoi)
• Thuộc tính: tên (ten), điểm (diem)
• Phương thức: gieo xúc xắc (gieoXucXac())
Trang 13• Phương thức: bắt đầu (batDau()), kết thúc (ketThuc), hiển thị thông tin (hienThi()), thực hiện trận đấu (thucHienTranDau())
Trang 14Xác định lớp
Trang 15Lớp XucXac
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 ; }
}
Trang 16Lớp NguoiChoi
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;
}
Trang 17Lớp NguoiChoi
public NguoiChoi(String ten){
this.ten=ten;
this.diem+=xucXac.getGiaTri();
System.out.println(" Diem: "
+ this.diem);
}
}
Trang 18Lớp TranDau
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;
}
Trang 19Lớp TranDau
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);
}
}
Trang 20Lớp TranDau
public void ketThuc(){
int diem1= nguoiChoi1.getDiem();
int diem2=nguoiChoi2.getDiem();
Trang 21Lớp TranDau
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());
Trang 22public 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();
}
}
Trang 23Bà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
• 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
Trang 24Kế thừa (Inheritance)
• Ngoài việc 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, con người thường nhóm các đối tượng có cùng một số thuộc tính/ hành vi
• Ví dụ: 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 ô tô, xe tải, )
Trang 26Kế thừa
• Ví dụ:
o Một cái xe ô tô “là một” xe động cơ
o Một cái xe tải “là một” xe động cơ
o Một cái xe máy “là một” xe động cơ
Dùng cấu trúc hướng đối tượng để định nghĩa quan hệ
“là một”
Trang 29Kế thừa
• Lớp cha – superclass (hoặc lớp cơ sở - base class)
Lớp tổng quát hơn trong mối quan hệ “là một”
Các đối tượng thuộc lớp cha có cùng tập thuộc tính và hành vi
Trang 30Kế thừa
• Lớp con – subclass (hoặc lớp dẫn xuất – derived class)
Lớp cụ thể hơn trong một quan hệ “là một”
Các đối tượng thuộc lớp con có cùng tập thuộc tính
và hành vi (do kế thừa 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
Trang 31Kế thừa
• Quan hệ “là một” còn gọi là sự kế thừa (inheritance)
• Ta nói rằng lớp con “kế thừa từ” lớp cha, hoặc lớp con
“được dẫn xuất từ” lớp cha
Kế thừa là quá trình tạo nên lớp mới bằng cách dẫn xuất từ lớp cũ
Trang 32Kế thừa
Ưu điểm của việc kế thừa
Tiết kiệm thời gian và công sức
Tái sử dụng lại những lớp có sẵn
Giảm lượng code phải thiết kế, viết, kiểm tra
Tránh trùng lắp code
Rút ngắn thời gian giúp LTV tập trung vào mục tiêu
Giúp phân loại và thiết kế lớp dễ dàng, dễ quản lý
Trang 33Kế thừa
• Phân loại
• Đơn kế thừa (single inheritance): chỉ có một lớp cha
• Đa kế thừa (multiple inheritance): có nhiều lớp cha
Trang 34Kế thừa
• 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)
• Ví dụ:
• 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)
Trang 35Ví dụ: Tam giác vuông là
một loại tam giác
Ví dụ: Tam giác có 3 đỉnh
Trang 36Ký hiệu kế thừa
Trang 37Sơ đồ quan hệ đối tượng
(Object Relationship Diagram – ORD)
Trang 38Sơ đồ quan hệ đối tượng
• Đối với những lớp dẫn xuất, chỉ cần liệt kê các thuộc tính/ hành vi mà lớp cơ sở không có
• Đơn giản hoá sơ đồ
• Nhấn mạnh các điểm
khác biệt
Trang 42• 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
Trang 43Chỉ định truy cập
• Chỉ định truy cập lớp:
• public : cho phép lớp con kế thừa nằm ở bất kỳ đâu
• Không chỉ định : chỉ cho phép lớp con kế thừa nằm cùng gói
• Chỉ định truy cập thành viên:
• public, protected : cho phép lớp con ở bất kỳ đâu được kế thừa thuộc tính/phương thức này, được truy cập vào thuộc tính/thành viên tương ứng trên lớp cha
• Không chỉ định : chỉ cho phép lớp con ở cùng gói đượ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
Trang 44Ví dụ chỉ định public cho class cha
Trang 45Ví dụ class con cùng gói
Trang 46Ví dụ class con khác gói
Trang 47Ví 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!!!
Trang 48Khởi tạo đối tượng trong kế thừa
• Lớp con không kế thừa phương thức khởi tạo của lớp cha
• Lớp cha phải được khởi tạo trước lớp con
• Các phương thức khởi tạo của lớp con tự động gọi phương thức khởi tạo mặc định của lớp cha (nếu có)
• Nếu lớp cha không có phương thức khởi tạo mặc định thì phải gọi phương thức khởi tạo khác mặc định của lớp cha
• Cú pháp: super(parameterList)
Trang 50Ví dụ khởi tạo đối tượng trong kế thừa
Trang 51Ví dụ khởi tạo đối tượng trong kế thừa
Trang 52Ví dụ khởi tạo đối tượng trong kế thừa (tt)
Trang 53Ví dụ khởi tạo đối tượng trong kế thừa (tt)
Trang 54Đối tượng cha và con
• Khi tạo đối tượng con, đối tượng cha được tạo ra độc lập
• Đối tượng con có tham chiếu tới đối tượng cha qua từ
khóa super (tham chiếu này là private)
• Trong lớp con, nếu truy cập tới thuộc tính/phương thức
của cha thì truy cập đó có được là qua từ khóa 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)
Trang 57Giả sử không dùng kế thừa
Trang 58public 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;
}
Trang 59public String getTenTruong() {
return tenTruong;
}
public void setTenTruong(String tenTruong) {
this.tenTruong = tenTruong;
public SinhVienKhongKeThua(String hoTen,
int tuoi, String tenTruong) {
Trang 60public void capNhatTinChi(int soLuong){
this.setTinChiTichLuy(this.getTinChiTichLuy()
+ soLuong);
}
public void hienThiThongTinSinhVien() {
System.out.println("- Ho va ten: " +
Trang 61private double heSoLuong; private int luongCoBan;
public String getHoTen() { return hoTen;
} public void setHoTen(String hoTen) { this.hoTen = hoTen;
} public int getTuoi() { return tuoi;
}
Trang 62public void setHocVi(String hocVi) {
this.hocVi = hocVi;
Trang 63public GiangVienKhongKeThua(String hoTen,
int tuoi, String tenTruong, String hocVi,
int heSoLuong, int luongCoBan){
Trang 65Sử dụng lớp kế thừa
Trang 67Cây kế thừa
Trang 68Lớp ConNguoi
public class ConNguoi {
private String hoTen;
private int tuoi;
private String tenTruong;
private String ngheNghiep;
public String getHoTen() {
public void setTuoi(int tuoi) {
this.tuoi = tuoi;
}
Trang 69#69 public String getNgheNghiep() {
Trang 70public ConNguoi(String hoTen, int tuoi,
String tenTruong) { this.setHoTen(hoTen);
Trang 71Lớp SinhVien
public class SinhVien extends ConNguoi{
private int tinChiTichLuy;
public int getTinChiTichLuy() {
Trang 72public SinhVien(String hoTen, int tuoi,
String tenTruong) {
super(hoTen, tuoi, tenTruong);
super.setNgheNghiep("Sinh vien");
this.setTinChiTichLuy( 0 );
}
public void capNhatTinChi(int soLuong) {
this.setTinChiTichLuy(this.getTinChiTichLuy()
Trang 73public class SinhVienTest {
public static void main(String []args) {
System.out.println("*** Tao doi tuong
con nguoi:");
ConNguoi nguoi = new ConNguoi("An", 17 , "");
System.out.println("*** Thong tin vua tao:"); nguoi.hienThiThongTinNguoi();
System.out.println("*** An tro thanh
sinh vien DH ABC:");
SinhVien sv = new SinhVien(nguoi.getHoTen(),
nguoi.getTuoi(), "Dai hoc ABC");
System.out.println("*** Thong tin sinh vien:"); sv.hienThiThongTinSinhVien();
System.out.println("*** An hoc xong mon
OOP in Java (4 tin chi)");
System.out.println("*** Cap nhat so tin chi
Trang 75Ví dụ
Trang 76Ví dụ
Trang 77• Nạp chồng phương thức (overloading): Giữ nguyên
tên phương thức và thay đổi danh sách tham số
!!! Giữ nguyên kiểu dữ liệu trả về của lớp cha
Trang 78Ví dụ 1
Trang 79Ví dụ 1 (tt)
Trang 80Ví dụ 2
Trang 81Ví dụ 2 (tt)
Trang 83Ví dụ
Lỗi
Trang 84Tính đa hình trong Java
Trang 85Tính đa hình trong Java
Trừu tượng hoá
Hiện thực đa hình trong Java
Trang 86Trừu tượng hoá
• Loại bỏ những thông tin cụ thể, giữ lại các thông tin chung
• Mức độ trừu tượng hoá được thể hiện trên cây kế thừa
Trang 87Định nghĩa lớp trừu tượng
• Sử dụng từ khoá abstract cho phương thức trừu tượng
• Bổ sung từ khoá abstract phía trước class
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;
}
Trang 88Đặ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
cụ thể tại lớp cha (kết thúc khai báo phương thức
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ó phương thức khởi tạo
Trang 91Ví dụ (tt)
Trang 92Lớp HinhHoc
Trang 93Lớp HinhTron
Trang 94Lớp HinhChuNhat
Trang 95Lớp HinhHocTest
Trang 96Giao diện (Interface)
Trang 97Giao 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
Trang 99Triển khai giao diện
Modifier class ClassName implements
Trang 100Kế thừa và triển khai giao diện
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
}
Trang 101Giao diện vs Trừu tượng
Chỉ được phép có thành viên
Mọi phương thức là trừu tượng
với chỉ định truy cập public
Ngoài phương thức trừu tượng, có thể có phương thức riêng
Không có phương thức khởi
Một lớp có thể triển khai nhiều
giao diện Một lớp chỉ có thể kế thừa từ một lớp trừu tượng
Trang 102Ví dụ
Trang 103Giao diện HinhHoc
Trang 104Lớp HinhTron
Trang 105Lớp HinhChuNhat
Trang 108Ví dụ
Trang 109Toá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
Trang 112Ghi đè phương thức 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:
• 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
Trang 113Ghi đè phương thức equals()
cho lớp ConNguoi
Trang 114Ghi đè phương thức equals()
cho lớp ConNguoi
Trang 115Lậ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ý
Trang 116Cách thức lập trình tổng quát
Trang 117Cách thức lập trình tổng quát
Trang 118Q&A