You are on page 1of 28

IT3100

LẬP TRÌNH HƯỚNG


ĐỐI TƯỢNG
Bài 07. Đa hình

1
Nội dung

1. Khái niệm Đa hình (Polymophism)


2. Liên kết tĩnh và Liên kết động
3. Upcasting và Downcasting
4. Đa hình phương thức

2
1/ ĐA HÌNH

3
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
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
Hướng đối tượng

Đóng gói
tượng hóa

Đa hình
Thừa kế
Trừu

5
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
Ví dụ
public class MainClass{
public class Parent{
public static void main(String []arg) {
public void show() {
Parent p = new Parent();
System.out.println("show from Parent");
p.show();
}
p.display();
void display() {
Child ch = new Child();
System.out.println("display from Parent");
ch.show();
}
ch.display();
}
}
public class Child extends Parent{
}
public void show() {
System.out.println("show from Child");
}
public void display() {
System.out.println("display from Child");
}
}

7
2/ UPCASTING VÀ
DOWNCASTING

8
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
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
Employee e = new Employee();

Kiểu dữ liệu Biến tham chiếu Đối tượng

 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
Hai loại chuyển đổi

Upcasting

Downcasting

11
https://www.youtube.com/watch?v=58Yhyg8Iw7A&t=1s
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

Kiểu dữ liệu Đối tượng tham chiếu tới


Biến tham chiếu

 Tự động chuyển đổi trong Java


class A{}
class B extends A{}
A a = new B();//day la upcasting
12
Ví dụ

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

13
Ví dụ Person p;
Employee e = new Employee();
p = e;

• Đố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

Thừa kế
phương thức được thừa kế, các e
phương thức của riêng lớp con không p
thể truy cập.

Bộ nhớ Stack Bộ nhớ Heap

14
Upcasting với phương thức ghi đè
 Trong trường hợp phương thức được thừa kế bị
ghi đè:

Thừa kế
+ ghi đè
e

=> 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.

15
Ví dụ 1
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();
}
}
16
https://gpcoder.com/
Ví dụ 2
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();

17
Đa hình tại runtime với upcasting
class Bike{
void run(){ 1. biến tham chiếu của lớp cha
System.out.println("dang chay"); gọi phương thức run
}
} 2. biến tham chiếu đang
class Splender extends Bike{ tham chiếu tới đối tượng
void run(){ của lớp con
System.out.println("chay an toan voi 60km");
}
3. phương thức lớp con ghi
public static void main(String args[]){ đè phương thức của lớp cha
Bike b = new Splender();
b.run(); 4.phương thức của lớp con
} được gọi tại runtime
}

18
Đ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 đè)

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);
}

19
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
Down-casting
// 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
21
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
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);

22
 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
Ví dụ
public class Parent{
public void show() { public class MainClass{
System.out.println("show from Parent"); public static void main(String []arg) {
} //Upcasting
void display() { Parent p = new Child();
System.out.println("display from Parent"); p.show();
} p.display();
} p.xyz();

//Downcasting
public class Child extends Parent{ Child ch = (Child) p;
public void display() { ch.show();
System.out.println("display from Child"); ch.display();
} ch.xyz();
public void xyz() { }
System.out.println("Child's Method"); }
}
}

24
Ưu điểm của sử dụng Upcasting
public abstract class Animal{ public class MainClass{
public abstract String speak(); public static void main(String []arg) {
} Animal[] animalArray = new Animal[3];
animalArray[0] = new Dog();
public class Dog extends Animal{ animalArray[1] = new Fox();
public String speak() { animalArray[2] = new Cow();
return "The dog says woof!";
} // Print out the array
} for(int i = 0; i < animalArray.length; i++) {
System.out.println(animalArray[i].speak());
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!";
}
}
25
Bài tập 1
 Kiểm tra các đoạn mã sau đây và vẽ sơ đồ
lớp tương ứng

26
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
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

You might also like