Đa hình(Polymorphism) trong java với ví dụ cụ thể

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 DogCat 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();

Animalnew Cat(), new Dog(). Animal là một base class, DogCat đều extends từ Animal. Hiểu nôm na là DogCat 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 DogCat đề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 DogCat

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 đó.

5 3 votes
Article Rating
Subscribe
Notify of
guest
1 Comment
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
1
0
Would love your thoughts, please comment.x
()
x