Tôi cũng đã được dạy điều này và tôi thích giao diện hơn nếu có thể (tất nhiên tôi vẫn sử dụng tính kế thừa ở nơi có ý nghĩa).
Một điều tôi nghĩ nó làm là tách mã của bạn khỏi các triển khai cụ thể. Giả sử tôi có một lớp được gọi là ConsoleWriter và điều đó được truyền vào một phương thức để viết một cái gì đó ra và nó ghi nó vào bàn điều khiển. Bây giờ hãy nói rằng tôi muốn chuyển sang in ra một cửa sổ GUI. Bây giờ tôi phải sửa đổi phương thức hoặc viết một phương thức mới lấy GUIWriter làm tham số. Nếu tôi bắt đầu bằng cách xác định giao diện IWriter và có phương thức trong IWriter, tôi có thể bắt đầu với ConsoleWriter (sẽ triển khai giao diện IWriter) và sau đó viết một lớp mới gọi là GUIWriter (cũng thực hiện giao diện IWriter) sẽ chỉ phải chuyển lớp đang được thông qua.
Một điều nữa (đúng với C #, không chắc chắn về Java) là bạn chỉ có thể mở rộng 1 lớp nhưng thực hiện nhiều giao diện. Hãy nói rằng tôi có một lớp có tên là Giáo viên, MathTeacher và HistoryTeacher. Bây giờ MathTeacher và HistoryTeacher mở rộng từ Giáo viên, nhưng điều gì sẽ xảy ra nếu chúng ta muốn một lớp đại diện cho một người vừa là MathTeacher và HistoryTeacher. Nó có thể trở nên khá lộn xộn khi cố gắng kế thừa từ nhiều lớp khi bạn chỉ có thể thực hiện từng lớp một (có nhiều cách nhưng chúng không chính xác tối ưu). Với các giao diện, bạn có thể có 2 giao diện được gọi là IMathTeacher và IHistoryTeacher và sau đó có một lớp mở rộng từ Giáo viên và thực hiện 2 giao diện đó.
Một nhược điểm của việc sử dụng giao diện là đôi khi tôi thấy mọi người trùng lặp mã (vì bạn phải tạo triển khai cho mỗi lớp thực hiện giao diện) tuy nhiên có một giải pháp rõ ràng cho vấn đề này, ví dụ như sử dụng những thứ như đại biểu (không chắc chắn Java tương đương với cái gì).
Suy nghĩ lý do lớn nhất để sử dụng các giao diện trên các thừa kế là việc tách mã thực thi nhưng đừng nghĩ rằng thừa kế là xấu vì nó vẫn rất hữu ích.