BÀI 5: LẬP TRÌNH KẾ THỪA
2. Lập trình lớp dẫn xuất
2.3. Xử lý thành viên kế thừa (tham chiếu super)
Trong các phần trước chúng ta sử dụng tham chiếu “this” để truy cập xử lý đối tượng hiện thời bên trong các phương thức của một lớp. Ở đây, khi một lớp dẫn xuất kế thừa các thành viên của một lớp cơ sở thì việc truy cập xử lý chúng được thực hiện theo 2 trường hợp:
- Nếu các thành viên kế thừa không trùng tên với các thành viên mới trong lớp dẫn xuất thì chúng ta truy cập xử lý như thông thường (chỉ cần viết tên của chúng là được);
- Nếu các thành viên kế thừa trùng tên với các thành viên mới trong lớp dẫn xuất thì chúng ta sử dụng tham chiếu “super” để truy cập xử lý, quy tắc như sau:
super.tên_thành_viên_kế_thừa_cần_truy_cập
Như vậy, trong một phương thức của lớp chúng ta có hai tham chiếu “this” và
“super” để truy cập xử lý. Minh họa bằng hình vẽ sau.
Đối tượng của lớp con “B” mang trong nó 2 phần nội dung, đó là nội dung được kế thừa từ lớp cha “A” (có tô màu) và nội dung của bản thân “B”. Do đó trong một phương thức bất kỳ của đối tượng này có tham chiếu “super” để truy cập xử lý phần nội dung kế thừa từ “A”, còn tham chiếu “this” để truy cập xử lý ngay chính đối tượng đó (phần nội dung của “B”).
Rõ ràng, tham chiếu “this” có thể được dùng để khai thác xử lý tất cả các thành viên trong đối tượng (gồm các thành viên kế thừa từ cơ sở và thành viên mới trong lớp con).
Ví dụ sau sẽ định nghĩa ba lớp theo sơ đồ kế thừa trong hình vẽ, lớp “Vehicle” là
cơ sở và các lớp con là “Car”, “Truck”, “Motorcycle”.
class Vehicle {
String bien_dk = "38F8-3338";
Lớp cơ sở: A
extends
Lớp dẫn xuất:
this B
super this
t
his supe
r
instance of
String ten_chuxe = "Duong Long Khanh";
void chuyenChuXe(String ten_chumoi) {
ten_chuxe = ten_chumoi;
}
void show(String title){
System.out.printf("%s",title);
System.out.printf("\nBien dang ky: %s",bien_dk);
System.out.printf("\nTen chu xe: %s",ten_chuxe);
}
//... các nội dung khác của lớp “Vehicle”
}
class Car extends Vehicle {
int so_cua = 4;
void show(String title){
super.show(title);
System.out.printf("\nSo canh cua: %d",so_cua);
}
//... các nội dung khác của lớp “Car”
}
class Truck extends Vehicle {
int so_cau = 3;
void show(String title){
super.show(title);
System.out.printf("\nSo cau (truc) xe: %d",so_cau);
}
//... các nội dung khác của lớp “Truck”
}
class Motorcycle extends Vehicle {
boolean co_mai_che = false;
void show(String title){
super.show(title);
if(co_mai_che) System.out.print("\nCo mai che");
else System.out.print("\nKhong co mai che");
}
//... các nội dung khác của lớp “Motorcycle”
}
Trong lớp “Vehicle” có hàm “show” để hiện các thông tin của đối tượng ra màn hình Console, cũng vậy các lớp con ở sau (kế thừa Vehicle) gồm “Car”, “Truck”,
“Motorcyle” đều chứa hàm “show” để hiện thông tin. Tuy nhiên, các nội dung cần hiện gồm phần được kế thừa và phần mới, trong khi phần được kế thừa đã thực hiện trong hàm “show” của lớp cơ sở “Vehicle” do đó chỉ cần gọi hàm này bằng lệnh,
super.show( ... );
trong các lớp con (dẫn xuất) là được. Sau đó viết lệnh hiện thêm các thông mới nếu có của lớp đối tượng tương ứng. Chẳng hạn, trong hàm “show” của lớp “Car” hiện thêm thông tin và số cửa, của lớp “Truck” hiện thêm thông về số cầu (trục) của xe,...
Hàm “show” của các lớp ở trên được thiết kế có tham số “title” chứa thông báo khi hiện thông tin của đối tượng. Nội dung thông báo này có thể thay đổi tùy theo thời điểm chạy của hàm trên cùng một đối tượng nên thiết kế dưới dạng tham số là hợp lý. Chẳng hạn, sau khi nhập của đối tượng “a” thuộc lớp “Car” ta viết lệnh hiện thông tin như sau,
a.show(“Thông tin xe vừa nhập”);
sau đó (trong khi xử lý) đối tượng xe hơi này bị chuyển chủ sở hữu bằng lệnh,
a.chuyenChuXe(“Duong Ha Linh”);
khi đó lệnh hiện thông tin đối tượng sẽ là,
a.show(“Thông tin xe sau khi chuyển chủ”);