Tìm hiểu về Đa hình trong JAVA

0
2335
Tim hiểu tính đa hình trong Java

Đa hình (Polymorphism) trong Java là một khái niệm để chỉ những hành động có thể thực hiện theo nhiều cách khác nhau.

Đa hình bắt nguồn từ 2 từ Hy Lạp: PolyMorphs. Từ ‘Poly‘ có nghĩa là nhiều và ‘Morphs‘ có nghĩa là hình thức.

Tim hiểu tính đa hình trong Java
Tim hiểu tính đa hình trong Java

Vì thế, Polymorphs (Đa hình) có nghĩa là nhiều hình thức.

Có hai loại đa hình trong Java:

  • Đa hình thời gian biên dịch (Compile-time)
  • Và Đa hình thời gian chạy (Runtime)

Chúng ta có thể thực hiện đa hình trong Java bằng cách Nạp chồng phương thứcGhi đè phương thức.

Nếu bạn nạp chồng một phương thức static trong Java, thì đó là ví dụ về đa hình thời gian biên dịch.

Ở bài này, chúng ta sẽ tập trung vào đa hình trong thời gian chạy (Runtime).

Đa hình trong Runtime

Đa hình trong thời gian chạy (Runtime polymorphism ) hoặc Công thức phương thức động (Dynamic Method Dispatch) là một quá trình trong đó một cuộc gọi đến một phương thức bị ghi đè được giải quyết trong thời gian chạy thay vì thời gian biên dịch.

Trong quá trình này, một phương thức được ghi đè được gọi thông qua biến tham chiếu của siêu lớp.

Việc xác định phương thức được gọi dựa trên đối tượng được tham chiếu bởi biến tham chiếu.

Để hiểu ngọn ngành về vấn đề này, trước tiên chúng ta hãy hiểu về sự upcasting trước.

Upcasting trong Java

Nếu biến tham chiếu của lớp cha đề cập đến đối tượng của lớp con, thì nó được gọi là upcasting. Ví dụ:

class A{}  
class B extends A{}
A a = new B(); // Đây là Upcasting

Để upcasting, chúng ta có thể sử dụng biến tham chiếu của class type hoặc interface type. Ví dụ:

interface I{}
class A{}
class B extends A implements I{}

Ở đây, mối quan hệ của lớp B sẽ là:

B IS-A A
B IS-A I
B IS-A Object

>> Nếu bạn chưa rõ thì vui lòng xem lại: Kế thừa IS-A trong Java

Vì Object là class root của tất cả các class trong Java, vì vậy chúng ta có thể viết B IS-A Object.

Ví dụ về đa hình thời gian chạy trong Java

Trong ví dụ này, chúng ta đang tạo hai lớp XeDapXeDapDien. Lớp XeDapDien mở rộng lớp XeDap và ghi đè phương thức run() của nó.

Chúng ta đang gọi phương thức run() bằng biến tham chiếu của lớp cha. Vì nó đề cập đến đối tượng lớp con và phương thức lớp con ghi đè phương thức lớp cha, nên phương thức lớp con được gọi trong thời gian chạy.

Do việc gọi phương thức được xác định bởi JVM chứ không phải trình biên dịch, nên nó được gọi là đa hình thời gian chạy.

class XeDap{  
    void run(){
        System.out.println("Đang chạy...");
    }  
}  
class XeDapDien extends XeDap{  
    void run(){
        System.out.println("Đang chạy với tốc độ 45km/h");
    }  

    public static void main(String args[]){  
        XeDap xe = new XeDapDien();//upcasting  
        xe.run();  
    }
}

Kết quả khi chạy chương trình:

Đang chạy với tốc độ 45km/h

Đa hình thời gian chạy Java với Data member

Một phương thức được ghi đè, không phải các data member, do đó các data member dữ liệu không thể đạt được tính đa hình thời gian chạy.

Trong ví dụ được đưa ra dưới đây, cả hai lớp đều có data member là tocDoToiDa. Chúng ta đang truy cập data member bằng biến tham chiếu của lớp cha, tham chiếu đến đối tượng lớp con.

Vì chúng ta đang truy cập data member không bị ghi đè, do đó, nó sẽ luôn truy cập vào data member của lớp cha.

class XeDap{  
    int tocDoToiDa = 30;
}
class XeDapDien extends XeDap{
    int tocDoToiDa = 60;

    public static void main(String args[]){
        XeDap klara = new XeDapDien();  
        System.out.println(klara.tocDoToiDa);
}

Kết quả khi chạy chương trình là:

60

Đa hình thời gian chạy với kế thừa đa cấp trong Java

Chúng ta hãy xem ví dụ đơn giản về Đa hình thời gian chạy với sự kế thừa đa cấp.

class DongVat{  
    void an(){System.out.println("Đang ăn");}  
}  
class Cho extends DongVat{  
    void an(){System.out.println("Gặm xương");}  
}  
class ChoCon extends Cho{  
    void an(){System.out.println("Uống sữa");}  
    public static void main(String args[]){  
        DongVat a, b, c;  
        a = new DongVat();  
        b = new Cho();  
        c = new ChoCon();
        a.an();
        b.an();
        c.an(); 
    }  
}

Kết quả khi chạy chương trình là:

Đang ăn
Gặm xương
Uống sữa

Bây giờ, thử với một thay đổi nhỏ như sau:

class DongVat{  
    void an(){System.out.println("Đang ăn");}  
}  
class Cho extends DongVat{  
    void an(){System.out.println("Gặm xương");}  
}  
class ChoCon extends Cho{
    public static void main(String args[]){
        DongVat c = new ChoCon();
        c.an();
    }
}

Kết quả khi chạy chương trình là:

Gặm xương

Mặc dù chúng ta đang gọi phương thức an() thông qua đối tượng của ChoCon. Nhưng class ChoCon không ghi đè phương thức an().

Thế nên phương thức ăn của class Cho được gọi.

Bạn đã hiểu về đa hình trong Java chưa?

Đa hình trong Java xoay quanh việc ghi đè phương thức và nạp chồng phương thức. Vì thế, bạn nắm vững hai khái niệm này là sẽ hiểu về đa hình trong Java.

Dĩ nhiên, càng sử dụng nhiều bạn sẽ càng hiểu rõ chúng. Và đừng lo nếu vẫn cảm thấy mông lung về tính đa hình trong Java. Hãy làm lại các ví dụ ở trên và đảm bảo hiểu rõ cách nó hoạt động.

>> Nếu bạn thích ngôn ngữ Java, tham khảo ngay: Tự học Java online (Toàn tập)

JavaDEV