Bai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinhBai07 da hinh
4. Khái niệm đa hình
Polymorphism: nhiều hình thể
thực hiện một hành động bằng nhiều cách khác nhau
Ví dụ: Nếu đi du lịch, bạn có thể chọn ô tô, thuyền,
hoặc máy bay
Dù đi bằng phương tiện gì, kết quả cũng giống nhau là bạn đến được
nơi cần đến
Cách thức đáp ứng các dịch vụ có thể khác nhau
4
5. Khái niệm đa hình
Là khái niệm quan trọng trong OOP
Là khả năng nhìn nhận đối tượng theo nhiều kiểu khác
nhau: một đối tượng này có khả năng nhập vai thành các
đối tượng khác
Là khả năng thực hiện một hành động nhưng bằng các
cách khác nhau:
• Nạp chồng phương thức
• Ghi đè phương thức
5
Trừu
tượng
hóa
Đa
hình
Hướng đối tượng
Đóng
gói
Thừa
kế
6. Khái niệm Liên kết tĩnh – động
Khi có nhiều phương thức cùng tên, phải xác định
phương thức nào sẽ được thực thi
Binding: quá trình liên kết lời gọi phương thức tới
đoạn code thực thi phương thức
Quyết định tại thời điểm biên dịch => Static Binding/Early
Binding/Compile-time Binding
Quyết định tại thời điểm chạy => Dynamic Binding/Late
binding/Run-time binding
Khi đó là phương thức nạp chồng
=> xác định phương thức được gọi tại thời điểm biên dịch: thông qua
chữ ký của phương thức
Khi đó là phương thức khởi tạo
=> xác định phương thức được gọi tại thời điểm biên dịch: thông qua
chữ ký của phương thức
Khi đó là phương thức ghi đè trong quan hệ thừa kế
=> xác định phương thức được gọi tại thời điểm chạy (do chữ ký là
hoàn toàn giống nhau), dựa trên đối tượng được tham chiếu tới
6
7. Ví dụ
7
public class Parent{
public void show() {
System.out.println("show from Parent");
}
void display() {
System.out.println("display from Parent");
}
}
public class Child extends Parent{
public void show() {
System.out.println("show from Child");
}
public void display() {
System.out.println("display from Child");
}
}
public class MainClass{
public static void main(String []arg) {
Parent p = new Parent();
p.show();
p.display();
Child ch = new Child();
ch.show();
ch.display();
}
}
9. Chuyển đổi kiểu dữ liệu
Chuyển đổi kiểu dữ liệu nguyên thủy (nhắc lại)
Java tự động chuyển đổi kiểu khi
• Kiểu dữ liệu tương thích
• Chuyển đổi từ kiểu hẹp hơn sang kiểu rộng hơn
Phải ép kiểu khi
• Kiểu dữ liệu không tương thích
• Chuyển đổi từ kiểu rộng hơn sang kiểu hẹp hơn
9
10. Tham chiếu của đối tượng
Cách duy nhất để truy cập đến một đối tượng là
thông qua biến tham chiếu
Một biến tham chiếu của kiểu dữ liệu X có thể được gán
cho (tham chiếu tới) một đối tượng có kiểu tương thích
(nằm trên cùng một cây phân cấp kế thừa với X)
Hai loại chuyển đổi
Up-casting
Down-casting
10
Employee e = new Employee();
Biến tham chiếu
Kiểu dữ liệu Đối tượng
11. Hai loại chuyển đổi
11
https://www.youtube.com/watch?v=58Yhyg8Iw7A&t=1s
Upcasting
Downcasting
12. Up-casting
Là khả năng nhìn nhận đối tượng thuộc lớp dẫn xuất như là
một đối tượng thuộc lớp cơ sở.
Chuyển 1 đối tượng là một thể hiện của lớp con lên thành đối
tượng là thể hiện của lớp cha
Biến tham chiếu của lớp cha tham chiếu tới đối tượng của lớp
con
Tự động chuyển đổi trong Java
12
class A{}
class B extends A{}
A a = new B();//day la upcasting
Biến tham chiếu
Kiểu dữ liệu Đối tượng tham chiếu tới
13. Ví dụ
13
public class Test1 {
public static void main(String arg[]){
Person p;
Employee e = new Employee();
p = e;
p.setName(“Hoa”); // ok
p.setSalary(350000); // compile error
}
14. Ví dụ
14
• Đối tượng e không bị thay đổi, e vẫn
tồn tại.
• Phép gán p=e cho phép ta gán một
“nhãn” khác cho đối tượng này
• Khi đó p chỉ truy cập được các
phương thức được thừa kế, các
phương thức của riêng lớp con không
thể truy cập.
e
Bộ nhớ Heap
Bộ nhớ Stack
p
Person p;
Employee e = new Employee();
p = e;
Thừa
kế
15. Upcasting với phương thức ghi đè
Trong trường hợp phương thức được thừa kế bị
ghi đè:
15
=> runtime binding: Việc quyết định phương thức được gọi dựa
trên bản chất đối tượng được tham chiếu tới, ở đây là Employee.
Phương thức getDetail() của lớp Employee được gọi.
e
p
Thừa
kế
+
ghi
đè
16. Ví dụ 1
16
class Animal {
public void eat() { System.out.println("eating..."); }
}
public class Cat extends Animal {
public void meow(){ System.out.println("meowing..."); }
}
public class Upcasting {
public static void main(String[] args) {
Cat cat = new Cat();
Animal animal1 = cat; // Tự động chuyển kiểu
Animal animal2 = (Animal) cat; // Chuyển kiểu TM
cat.eat();
cat.meow();
animal1.eat();
animal2.eat();
animal2.meow();
}
}
https://gpcoder.com/
17. Ví dụ 2
17
public class Cat extends Animal {
@Override phương thức eat của lớp Animal
public void eat() {
System.out.println("Eat meat");
}
public void meow() {
System.out.println("meowing...");
}
}
Lời gọi từ hàm main()
cat.eat();
cat.meow();
animal1.eat();
animal2.eat();
18. Đa hình tại runtime với upcasting
18
class Bike{
void run(){
System.out.println("dang chay");
}
}
class Splender extends Bike{
void run(){
System.out.println("chay an toan voi 60km");
}
public static void main(String args[]){
Bike b = new Splender();
b.run();
}
}
1. biến tham chiếu của lớp cha
gọi phương thức run
2. biến tham chiếu đang
tham chiếu tới đối tượng
của lớp con
3. phương thức lớp con ghi
đè phương thức của lớp cha
4.phương thức của lớp con
được gọi tại runtime
19. Đa hình tại runtime với upcasting (2)
Đa hình tại runtime không hoạt động với thuộc tính
(kể cả bị ghi đè)
19
class Bike{
int speedlimit=90;
}
class Honda3 extends Bike{
int speedlimit=150;
}
public static void main(String args[]){
Bike obj=new Honda3();
System.out.println(obj.speedlimit);
}
20. Down-casting
Là khả năng nhìn nhận một đối tượng thuộc lớp
cơ sở như một đối tượng thuộc lớp dẫn xuất.
Chuyển 1 đối tượng là một thể hiện của lớp cha
xuống thành đối tượng là thể hiện của lớp con
Không tự động chuyển đổi kiểu
không phải mọi thể hiện của lớp cơ sở đều là thể hiện của
lớp dẫn xuất => cần chuyển đổi tường minh
20
21. Down-casting
21
// Compile error: Yêu cầu chuyển đổi tường minh
// Runtime error:
// yêu cầu JVM thực hiện chuyển kiểu
// JVM phát hiện Kiểu của animal lúc chạy là Animal
// animal không thực là một Dog
// Is Animal a Dog? No it isn't - it cannot be cast.
// => báo lỗi ClassCastException
// Upcasting
// Compile error: Yêu cầu chuyển đổi tường minh
// "Type mismatch: cannot convert from Animal to Dog"
// Upcasting
// Downcasting Tường minh => OK
// Khi upcasting: che dấu các thuộc tính của Dog
// Khi Downcasting: quay lại sử dụng được các thuộc
// tính này
22. Down-casting
Để tránh lỗi ClassCastException => cần kiểm tra một đối tượng
có phải là thể hiện của một kiểu dữ liệu tương thích không ! =>
sử dụng instanceof
22
public class Dog extends Animal
static void check(Object obj) {
if (obj instanceof Dog) {
Dog dog = (Dog) obj; // downcasting
System.out.println("ok downcasting performed");
} else {
System.out.println("obj is not instance of Dog");
}
}
Animal dog = new Dog();
Dog.check(dog);
Object obj = new Rectangle();
Dog.check(obj);
23. Nguyên tắc: một đối tượng A chỉ được tham
chiếu tới bởi các biến tham chiếu kiểu A, hoặc
biến tham chiếu có kiểu là các lớp cha của A.
Ngược lại sẽ bị lỗi (lớp con của A, lớp không
có quan hệ tới A)
23
24. Ví dụ
24
public class Parent{
public void show() {
System.out.println("show from Parent");
}
void display() {
System.out.println("display from Parent");
}
}
public class Child extends Parent{
public void display() {
System.out.println("display from Child");
}
public void xyz() {
System.out.println("Child's Method");
}
}
public class MainClass{
public static void main(String []arg) {
//Upcasting
Parent p = new Child();
p.show();
p.display();
p.xyz();
//Downcasting
Child ch = (Child) p;
ch.show();
ch.display();
ch.xyz();
}
}
25. Ưu điểm của sử dụng Upcasting
25
public abstract class Animal{
public abstract String speak();
}
public class Dog extends Animal{
public String speak() {
return "The dog says woof!";
}
}
public class Fox extends Animal{
public String speak() {
return "What does the fox say?";
}
}
public class Cow extends Animal{
public String speak() {
return "The cow goes moo!";
}
}
public class MainClass{
public static void main(String []arg) {
Animal[] animalArray = new Animal[3];
animalArray[0] = new Dog();
animalArray[1] = new Fox();
animalArray[2] = new Cow();
// Print out the array
for(int i = 0; i < animalArray.length; i++) {
System.out.println(animalArray[i].speak());
}
}
}
26. Bài tập 1
Kiểm tra các đoạn mã sau đây và vẽ sơ đồ
lớp tương ứng
26
27. Bài tập 2
Giải thích các đầu ra (hoặc các lỗi nếu có)
cho chương trình thử nghiệm sau:
27
28. Bài tập 3
Phân tích xây dựng các lớp như mô tả sau:
Hàng điện máy <mã hàng, tên hàng, nhà sản xuất, giá, thời
gian bảo hành, điện áp, công suất>
Hàng sành sứ < mã hàng, tên hàng, nhà sản xuất, giá, loại
nguyên liệu>
Hàng thực phẩm <mã hàng, tên hàng, nhà sản xuất, giá,
ngày sản xuất, ngày hết hạn dùng>
Viết chương trình tạo mỗi loại một mặt hàng cụ
thể. Xuất thông tin về các mặt hàng này.
28