Thừa kế một tính năng quan trọng trong lập trình hướng đối tượng. Thông thường ở các ngôn ngữ khác như C/C++ chúng ta sẽ có đơn thừa kế và đa thừa kế. Nhưng với ngôn ngữ java chỉ hỗ trợ đơn thừa kế.
Diamond Problem
Trong đa thừa kế chúng ta sẽ gặp tình huống, giữa các class được thừa kế có những thuộc tính và method cùng tên.
Trong trường hợp trên, đối với những thuộc tính và method có cùng tên thì class con sẽ không biết sử dụng của class cha nào. Được gọi là Diamond Problem.
Cùng theo dõi ví dụ sau
// File A.java public class A { public void disp() { System.out.println("A disp() called"); } } // File B.java public class B extends A { @Override public void disp() { System.out.println("B disp() called"); } } // File C.java public class C extends A { @Override public void disp() { System.out.println("C disp() called"); } } // File D.java // Với file D chúng ta sẽ gặp lỗi compile vì D không được thừa kế từ 2 class cha đâu nhé. public class D extends B,C public static void main(String args[]) { D d = new D(); d.disp(); } }
Ở trên chúng ta có class B và C entends A và chúng override lại method disp(). Đều này là hoàn toàn hợp lệ.
Thế nhưng D lại extends của B, C đều này là không được phép. Chúng ta cả B, C đều có method disp(). Class D sẽ không biết dùng method disp() của thằng nào. Kết quả chúng ta sẽ bị lỗi biên dịch.
Đa thừa kế trong java
Đọc tiêu đề có vẽ lạ, thằng này mới vừa nảy nói java chỉ hỗ trợ đơn thừa, giờ lại đa thừa kế gì nữa đây =).
Đúng thật, java chỉ hỗ trợ đơn thừa kế. Thế nhưng không cách này thì cách khác, chúng sẽ biến tấu một xíu để có một đa thừa kế trong java không chính thống.
Note: Có rất nhiều cách để implement đa thừa kế trong java, đây chỉ là cách của mình theo kinh nghiệm mình đã từng làm trong java thôi nhé. Các bạn có thể tự đề ra mô hình cho mình và triển khai nó trên dự án của bạn.
Chúng ta cần nhớ lại một chút kiến thức về abstract class, interface và quan hệ has – a trong java.
Chúng ta sẽ có class D extends A, tới đây chúng ta mới chỉ có đơn thừa kế. Chúng ta có interface B và một class C sẽ implement B. Sau đó chúng ta chỉ cần khai báo trong B thuộc tính B và khởi tạo object C cho B.
// File Car.java public class Car { void dispCategory(){ System.out.println("Car"); } }
// File Vehicle.java public interface Vehicle { void maxSpeed(); }
public class VehicleImpl implements Vehicle { @Override public void maxSpeed() { System.out.println("Max speed is 200km/h"); } }
// File Bus.java public class Bus extends Car { Vehicle vehicle; Bus() { vehicle = new VehicleImpl(); } void getSpeed() { dispCategory(); vehicle.maxSpeed(); } }
// File Main.java public class Main { public static void main(String[] args) { Bus bus = new Bus(); bus.getSpeed(); } }
Output:
Car
Max speed is 200km/h