Mục lục
Khái niệm
Đa hình là một khái niệm quan trọng trong lập trình hướng đối tượng. Cho phép chúng ta thực một hành động theo nhiều cách khác khác nhau.
Ví dụ: Chúng ta có class Animal có method sound(), class Animal là base class cho tất cả các loài động, ví dụ như Cat thì nó sẽ kêu là meo meo Dog kêu là gau gau.
Chúng ta sẽ tiến hành định nghĩa base class Animal
// File Animal.java public class Animal{ public void sound(){ System.out.println("Animal keu"); } }
Tiếp theo là 2 class Dog và Cat thừa kế từ class Animal
// File Dog.java public class Dog extends Animal{ @Override public void sound(){ System.out.println("gau gau"); } }
// File Cat.java public class Cat extends Animal{ @Override public void sound(){ System.out.println("meo meo"); } }
// File Main.java public class Main { public static void main(String[] args) { Animal cat = new Cat(); Animal dog = new Dog(); cat.sound(); dog.sound(); } }
Output
meo meo
gau gau
Các bạn để ý đoạn code ở Main
Animal cat = new Cat(); Animal dog = new Dog();
Animal mà new Cat(), new Dog(). Animal là một base class, Dog và Cat đều extends từ Animal. Hiểu nôm na là Dog và Cat là 2 biểu hiện khác nhau nhưng đều cùng loại là Animal.
Cho nên đoạn code trên là hoàn toàn đúng, và nó có ý nghĩa rất lớn trong lập trình hướng đối tượng mà chúng ta sẽ nói ở phần cuối.
Như các bạn thấy ở trên, mỗi class con Dog và Cat đều đã định nghĩa là sound() riêng của nó. Như vậy class Animal sẽ có nhiệm vụ cung cấp một cấu trúc chung là tất cả các class con, các class con có thể sử dụng lại hoặc implement theo cách riêng tuỳ vào các đặc tính của nó. Ví dụ mèo thì phải kêu meo meo, chó thì kêu gau gau.
Áp dụng đa hình trong java
Đa hình cho phép thực hiện các hành động khác nhau dựa trên các đối tượng cụ thể. Đa hình cho phép chúng ta định nghĩa một interface – khuôn mẫu và nhiều implement khác nhau. Như ví dụ ở trên chúng ta thấy Animal có method mẫu là sound() và các implement sound() của 2 class Dog và Cat.
Chúng ta có các kiểu đa hình:
- Đa hình compile time – Method Overloading
- Đa hình runtime – Method Overrding
Đa hình compile time
Đa hình được giải quyết tại thời biên dịch được gọi là đa hình tại compile time. Method Overloading là một ví dụ điển hình.
Method Overloading: Cho phép chúng ta có nhiều phương thức cùng tên nhưng khác nhau về số lượng và kiểu dữ liệu của các tham số đầu vào.
// File Operator.java public class Operator { int add(int a, int b) {return a + b;} int add(int a, int b, int c) {return a + b + c;} String add(String a, String b) {return a + b;} }
// File Main.java public class Main { public static void main(String[] args) { Operator operator = new Operator(); System.out.println(operator.add(1, 3)); System.out.println(operator.add(1, 3, 5)); System.out.println(operator.add("Hello ", "anh em")); } }
Output:
4
9
Hello anh em
Chúng ta có 3 phương thức add(), việc chúng ta sử dụng hàm nào là tuỳ thuộc vào các tham số và được xác định tại thời điểm compile time.
Đa hình tại runtime
Đa hình tại runtime là một quá trình xử lý gọi method được ghi đè tại thời điểm chạy chương trình.
Method Overrding: Cho phép chúng ta định nghĩa lại method của class con mà trước đó nó đã được định nghĩa ở class cha.
Chúng ta sẽ bàn luận lại ví dụ ở đầu bài
// File Animal.java public class Animal{ public void sound(){ System.out.println("Animal keu"); } }
Class Animal đã định nghĩa method sound().
// File Dog.java public class Dog extends Animal{ @Override public void sound(){ System.out.println("gau gau"); } }
// File Main.java public class Main { public static void main(String[] args) { Animal dog = new Dog(); dog.sound() } }
Output: gau gau
Anotation @Override được đặt trước method có ý nghĩa rằng method này đã được định nghĩa ở class cha, nhưng tui không muốn sử dụng và tui muốn implement lại ok =).
Ý nghĩa của đa hình trong lập trình hướng đối tượng
Đa hình cho phép khởi tạo các class con dựa trên base class. Tại thời điểm run tine, trình biên dịch sẽ dựa vào lúc chúng ta khởi tạo mà tự nhận diện được class con.
Ở trên mặc dù chúng ta viết
Animal cat = new Cat(); Animal dog = new Dog(); cat.sound(); dog.sound();
Nhưng kết quả vẫn nó vẫn thực hiện code ở 2 class con Dog và Cat.
Nếu như không có đa hình, việc chúng ta duyệt 2 tập dữ liệu Dog và Cat sẽ như sau
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Dog> dogs = new ArrayList<>(); List<Cat> cats = new ArrayList<>(); // add data for dogs and cats dogs.add(new Dog()); cats.add(new Cat()); for(Dog item : dogs) { item.sound(); } for(Cat item : cats) { item.sound(); } } }
Áp dụng đa hình
public class Main { public static void main(String[] args) { List<Animal> animals = new ArrayList<>(); animals.add(new Dog()); animals.add(new Cat()); for (Animal item: animals) item.sound(); } }
Output:
gau gau
meo meo
Áp dụng đa hình chúng ta khỏi mất công phải kiểm tra, thực hiện các đoạn code dựa theo các object riêng lẽ. Mà đa hình sẽ thay chúng ta làm việc đó.