Đây là 1 trong những câu hỏi thường gặp khi phỏng vấn vị trí mà phải code ví dụ như dev junior và automation tester.
Điểm khác biệt cốt lõi cửa 2 thằng này đến từ tư tưởng sử dụng, ko phải đến từ việc thằng này có abc, thằng kia có xyz.
- Interface giống như 1 bản hợp đồng (contract), tất cả các class implementation của nó phải tuân theo bản hợp đồng đấy. Vì sao lại là contract thì đọc tiếp bên dưới.
- Abstract class là dùng để thừa kế, mối quan hệ cha-con. Tất cả các class con sẽ được thừa kế những gì của class cha
Nếu nhìn vào điểm khác nhau bạn có thể sẽ nghĩ là “2 thứ nó khác nhau rõ ràng như thế này, sao người ta lại đặt ra câu hỏi là phân biệt 2 thứ này nhỉ?”. Tuy nhiên trên thực tế, nhất là trong Java, về mặt functional thì Interface và Abstract class ko khác nhau nhiều. Sau khi bản update ở Java 8, thì Interface và Abstract class lại càng giống nhau hơn.
Nếu bạn so sánh 2 thằng này mà sa đà vào việc đếm thành phần như Interface thì tất cả method ko có nội dung hay Abstract thì có state thì bạn sẽ rơi vào vòng luẩn quẩn, học như thế rất mệt mỏi và sẽ rất rối.
Nội dung bài viết
I. Thế nào là contract?
Về ý nghĩa nói chung, interface trong lập trình như là cách giao tiếp giữa các component, nó ẩn phần implementation. Lấy 1 ví dụ đời thường, coi như chuẩn TypeC kết nối giữa máy tính và màn hình là 1 interface.
- Máy tính là
Client
Interface
là TypeC- Màn hình Dell, màn hình HP, màn hình ThinkPad là
Implementation
của Interface
TypeC định nghĩa là tất cả các màn hình mà có theo chuẩn TypeC thì đều phải có 2 method là: âm thanh sound()
và hình ảnh display()
, để khi máy tính kết nối vào bất kỳ cái màn hình nào cũng sẽ gọi được 2 method này. Contract ở đây là hợp đồng giữa client và interface. Nhiệm vụ của interface lúc này là sẽ force (ép buộc) tất cả các implementation phải tuân theo bản hợp đồng đó –> compile error nếu implementation nào ko override method của interface.
II. Chỗ nào cho Abstract class?
Thông thường, nếu 2 class có những điểm chung về code thì ta sẽ viết các điểm chung đó vào class cha và viết điểm riêng vào 2 class con.
Giả sử cả 3 Implementation ở ví dụ trên đều có phần code method sound()
là giống nhau, thì tốt nhất là ta nên chuyển method sound
lên Abstract class.
- Vì Abstract class phải implement interfact TypeC, do đó nó phải implement cả 2 method
sound()
vàdisplay()
, nhưng nó lại ko muốn implement methoddisplay()
vì đây là phần riêng của mỗi implementation nên ở nó sẽ đánh dấu method này làabstract,
những class con phải tự override. - Do thằng class cha này có 1 method dạng abstract –> class cha này ko phải là 1 thực thể, nó chỉ là 1 thằng cha ảo và nó ở trạng thái imcomplete (có method abstract – ko có nội dung của method), để tránh side effect, java force (bắt buộc) phải có keyword
abstract
chỗ class để client ko thể khởi tạo nhầm.
Bạn có thể sẽ nhìn thấy cái pattern này ở trong nhiều thư viện khác nhau và giờ chắc bạn đã hiểu vì sao ở các thư viện, nó cho phép mình viết custom implementation thì người ta thường hướng dẫn bạn nên extend từ Abstract class thay vì implement trực tiếp từ Interface.
Nếu bạn vẫn chưa hiểu vì sao thì đây là câu trả lời:
- Interface trong các thư viện thường được extend từ 1 vài interface khác nên nó thường có rất nhiều method. Nếu mình implement trực tiếp từ các Interface đó thì mình sẽ phải đọc rất nhiều các defined implementation của ngta để biết phải viết cái gì.
- Tuy nhiên, nếu mình extend từ Abstract class thì mình chỉ phải implement 1 hoặc 2 methods thôi, như thế dễ cho mình hơn.
III. Kết luận
Bài này mình chỉ tập trung là điểm khác biệt về mặt tư tưởng của Interface và Abstract class, nhưng điểm khác biệt và giống nhau về mặt chức năng thì bạn nên xem kỹ vào từng ngôn ngữ. Hi vọng bài viết có ích cho bạn và khiến bạn cảm thấy tự tin hơn khi đọc và viết code.