🎥 Video minh họa nguồn: YTB Code Thu
1) Đa hình là gì?
Đa hình (Polymorphism) cho phép một đối tượng có nhiều “hình dạng” khác nhau:
- Một method có thể có nhiều cách thực hiện
- Một đối tượng có thể được xem như nhiều kiểu khác nhau
2) Compile-time Polymorphism (Method Overloading)
public class Calculator {
// Cùng tên method, khác tham số
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
3) Runtime Polymorphism (Method Overriding)
class Animal {
public void makeSound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
// Sử dụng
Animal animal1 = new Dog(); // Đa hình
Animal animal2 = new Cat(); // Đa hình
animal1.makeSound(); // "Woof!"
animal2.makeSound(); // "Meow!"
4) Upcasting & Downcasting
4.1. Upcasting
Chuyển đổi từ class con lên class cha (tự động)
Dog dog = new Dog();
Animal animal = dog; // Upcasting
4.2. Downcasting
Chuyển đổi từ class cha xuống class con (cần kiểm tra)
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // Downcasting
dog.bark();
}
5) Đa hình với Interface
interface Playable {
void play();
}
class Guitar implements Playable {
@Override
public void play() {
System.out.println("Playing guitar...");
}
}
class Piano implements Playable {
@Override
public void play() {
System.out.println("Playing piano...");
}
}
// Sử dụng
Playable instrument1 = new Guitar();
Playable instrument2 = new Piano();
instrument1.play(); // "Playing guitar..."
instrument2.play(); // "Playing piano..."
6) Best Practices
6.1. Programming to Interface
// Thay vì
ArrayList<String> list = new ArrayList<>();
// Nên dùng
List<String> list = new ArrayList<>();
6.2. Sử dụng @Override
@Override // Giúp compiler kiểm tra
public void makeSound() {
System.out.println("Woof!");
}
6.3. Kiểm tra type trước khi cast
if (obj instanceof Dog) {
Dog dog = (Dog) obj;
} else {
// Xử lý trường hợp khác
}
7) Kết luận & cảm nhận
- Đa hình giúp code linh hoạt, dễ mở rộng
- Kết hợp với interface tạo code loosely coupled
- Cẩn thận với downcasting để tránh lỗi runtime