Phân biệt abstract class và interface

Chào mừng các bạn đã quay trở lại với thachleblog. Bài viết hôm nay mình sẽ trình bày về abstraction trong Java. Chuyện là lần đầu tiên đi làm, được train để join vào 1 dự án của Directv bên Fsoft. Sau một thời gian đọc code, điều mình ấn tượng là các tính năng đều được implement từ các interface. Lúc đó mình đã không hiểu được tại sao lại phải dùng đến interface trong khi chúng ta có thể sử dụng các class có implement (stupid question, haha). Do đó, bài viết hôm nay sẽ giới thiệu về giải thích tại sao lại cần dùng đến interface và abstract class. Nào, chúng ta cùng bắt đầu nhé.

phan biet abstract class va interface

Khái quát

Abstraction là một trong 4 đặc tính quan trọng trong lập trình hướng đối tượng bao gồm, Abstraction (tính trừu tượng hóa), Inheritance (tính kế thừa), Polymorphisms (tính đa hình), Encapsulation (tính đóng gói).

Abstraction hiểu là nôm na là trừa tượng hóa, là thiết kế chỉ hiện thị chức năng, che giấu implementation. Nghe có vẻ khó hiểu, chúng ta cùng đi qua ví dụ nhé.

Thử tưởng tượng chiếc xe gắn máy của bạn không có lớp vỏ bọc ngoài, toàn bộ các dây điện, mạch, động cơ, hộp số, bình xăng… đều để lộ ra bên ngoài, mặc dù có khả năng chạy tốt nhưng chắc không ưa nhìn tí nào đâu nhỉ. Theo mình nghĩ bản chất của phần mềm, module cũng thế. Các module giao tiếp với nhau bằng các tính năng mà ta gọi là API, các phần mềm giao tiếp với người dùng qua các chức năng, che giấu đi phần implement bên trong.

Trong Java, abstraction được thể hiện qua abtract class và interface, đó là thiết kế mà thông thường chỉ thể hiện chức năng ra bên ngoài (thông qua API) và che giấu implementation. Ta cùng xem abstract class Number và interface Comparable trong Java.

Ví dụ

  • Abstract class Number:
  1. package java.lang;
  2. import java.io.Serializable;
  3. public abstract class Number implements Serializable {
  4. private static final long serialVersionUID = -8742448824652078965L;
  5. public abstract int intValue();
  6. public abstract long longValue();
  7. public abstract float floatValue();
  8. public abstract double doubleValue();
  9. public byte byteValue() {
  10. return (byte) this.intValue();
  11. }
  12. public short shortValue() {
  13. return (short) this.intValue();
  14. }
  15. }

Number có các extends: Byte, Double, Float, …

public final class Byte extends Number implements Comparable
public final class Double extends Number implements Comparable
public final class Float extends Number implements Comparable

  • Interface Comparable
  1. package java.lang;
  2. public interface Comparable {
  3. int compareTo(T arg0);
  4. }

Comparable có các implementation: Date, String, Calendar… 

public class Date extends Object implements Serializable, Cloneable, Comparable
public final class String extends Object implements Serializable, Comparable, CharSequence
public abstract class Calendar extends Object implements Serializable, Cloneable, Comparable

Khác biệt chính của abstract class và interface

  • Abstract class có thể có concrete method (method có implement), interface chỉ có abstract method (Tuy nhiên, đối với Java 8, interface đã có thể có defaut method, mình sẽ viết 1 bài chi tiết về những điểm mới của Java 8)
  • 1 class chỉ được extends 1 abstract class, 1 class có thể implement nhiều interface

Khi nào dùng Abstract class và khi nào dùng interface?

– Sử dụng abstract class khi các class được extends có nhiều điểm chung và có mối quan hệ với nhau, và ta quan tâm chúng là gì, ở đây ta nói Byte, Double, Float… “là” Number.
– Sử dụng interface khi ta muốn chức năng được dùng chung bởi các implement class mà không quan tâm chúng là gì.

Ta không nói Date, String, Calendar là Comparable mà là “có khả năng” Comparable. Một đặc điểm quan trọng để sử dụng thiết kế interface nữa đó là có khả năng implement multi interface. Ví dụ String implement từ 3 interface đó là Serializable, Comparable và CharSequence.

Tùy từng trường hợp mà ta lựa chọn thiết kế sử dụng abstract class hay interface nhưng thông thường trong các thiết kế phần mềm, người ta ưu tiên lựa chọn thiết kế sử dụng interface để tăng tính flexible cho ứng dụng, flexible như thế nào thì các bạn có thể đọc trong Effective Java, 2nd Edition, Item 18: Prefer interfaces to abstract classes, rất dễ hiểu, hehe.

Hy vọng bài viết vừa rồi của mình giúp các bạn hiểu hơn về đặc tính abstraction trong hướng đối tượng và có được lựa chọn thiết kế sử dụng abstract class hoặc interface cho ứng dụng của mình. Về câu chuyện ở đầu bài thì sau này mình mới biết đó là thiết kế theo Factory design pattern (sẽ có bài về pattern này).

Hẹn gặp lại các bạn ở những bài viết sau. Mong nhận được ý kiến đóng góp của tất cả các bạn.

Xin cảm ơn!

Tham khảo thêm:
https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
http://www.javatpoint.com/difference-between-abstract-class-and-interface