So sánh theo nhiều yêu cầu trong java

Bài viết này sẽ giới thiệu về abstract class và interface trong Java, đồng thời so sánh sự khác nhau giữa chúng 🙂

1. Abstract Class (Lớp trừu tượng)

Một lớp trừu tượng khi khai báo phải có từ khóa abstract

Một lớp trừu tượng thì ta không thể khởi tạo nó trực tiếp bằng toán tử new

Một lớp trừu tượng có thể khai báo 0, 1 hoặc nhiều method trừu tượng (method đặt là abstract) bên trong. Và chúng không được có thân hàm

Một lớp trừu tượng thì bên trong nó có những method đặt là abstract (không có thân hàm), có method không đặt là abstract (có thân hàm)

Các Subclasses sử dụng từ khóa “extends” để extend một abstract class và chúng cần phải implementation tất cả các method được khai báo abstract trong abstract class ( trừ khi subclass cũng là abstract class)

Ví dụ với Abstract Class

File Shape.java

So sánh theo nhiều yêu cầu trong java

File Square.java

So sánh theo nhiều yêu cầu trong java

File Circle.java

So sánh theo nhiều yêu cầu trong java

File Circle_1.java

So sánh theo nhiều yêu cầu trong java

File TestShape.java

So sánh theo nhiều yêu cầu trong java

Kết quả

So sánh theo nhiều yêu cầu trong java

2. Interface

Như chúng ta đã biết một lớp trong Java chỉ có một siêu lớp (super class) trực tiếp hay một cha duy nhất (đơn thừa kế). Để tránh đi tính phức tạp của đa thừa kế (multi-inheritance) trong lập trình hướng đối tượng, Java thay thế bằng interface. Một lớp có thể kế thừa từ nhiều interface để thừa hưởng thêm vùng dữ liệu và phương thức của các interface này.

Để khai báo một interface dùng từ khóa interface

Các đặc điểm của Interface

  • Giống với class, interface cũng chỉ có 2 loại access modifiers là public & default
  • public: truy cập tự do từ bên ngoài (every where)
  • default: chỉ truy cập được trong nội bộ một package
  • Interface không có constructor
  • Về thuộc tính trong interface:

Các thuộc tính trong interface được gọi là hằng số (khai báo kèm theo từ khóa final) và mặc định có 3 đặc điểm là public static final (vì là hằng số nên tên thường được viết hoa)

public static final int AGE = 22;

Nếu ta chỉ khai báo thuộc tính trong interface là

int AGE = 22;

thì vẫn không sai, và Java sẽ ngầm hiểu đó là public static final int AGE = 22

– Về phương thức trong interface:

Những phương thức trong interface thì mặc định có 2 đặc điểm là public abstract. Vì là abstract nên không được có thân hàm (chứ không hỗn hợp như abstract class phương thức vừa có thân hàm, vừa không có, như Shape.java ở trên)

public abstract void show();

Nếu ta chỉ khai báo phương thức trong interface là

public void show();

thì vẫn không sai, và Java sẽ ngầm hiểu là public abstract void show()

  • Sử dụng từ khóa extends để một interface thừa kế lại một interface
  • Sử dụng từ khóa implements để một class thừa kế lại một interface
  • Sau từ khóa implements được phép thừa kế nhiều Interface và cách nhau bởi dấu phẩy. Sau từ khóa extends không được thừa kế từ nhiều lớp, interface

Ví dụ với Interface

So sánh theo nhiều yêu cầu trong java

File CanMove.java

So sánh theo nhiều yêu cầu trong java

File CanDrink.java

So sánh theo nhiều yêu cầu trong java

File CanEat.java

So sánh theo nhiều yêu cầu trong java

File Animal.java

So sánh theo nhiều yêu cầu trong java

File Cat.java

So sánh theo nhiều yêu cầu trong java

File Mouse.java

So sánh theo nhiều yêu cầu trong java

File AnimalDemo.java

So sánh theo nhiều yêu cầu trong java

Kết quả

So sánh theo nhiều yêu cầu trong java

Câu hỏi: Tại sao Java cho phép đa thừa kế (Multiple Inheritance) với Interface mà không hỗ trợ đa thừa kế với Class?

Ví dụ một class A kế thừa từ class B và class C, giả sử cả B và C đều có chung một hàm giống hệt nhau đều có thân hàm ==> Vậy nếu A gọi hàm đó thì sẽ gọi hàm của B hay của C đây?

Để tránh sự nhầm lẫn này Java hỗ trợ đa thừa kế với interface.

Ví dụ class A implements interface B và interface C, giả sử cả B và C đều có chung một hàm giống hệt nhau nhưng cả 2 hàm đều không có thân hàm, lúc đó dù A thừa kế thằng nào thì đều phải viết lại thân hàm.

3. Sự khác nhau giữa Abstract Class và Interface trong Java

So sánh theo nhiều yêu cầu trong java

Việc lựa chọn giữa abstract class và interface là một quyết định phụ thuộc vào nhiều yếu tố. Bạn hãy xem khi nào sử dụng abstract class và khi nào sử dụng interface là giải pháp tốt nhất:

1. Java không hỗ trợ “multiple class level inheritance” tạm dịch “đa thừa kế lớp”, do đó, mọi class chỉ có thể có một super class. Nhưng một class lại có thể implement nhiều interface. Do vậy, trong hầu hết các trường hợp, interface là một sự lựa chọn đúng đắn cho việc cung cấp base contract cho class hierarchy.

2. Nếu có nhiều phương thức trong contract, thì bạn nên sử dụng abstract class vì nó cung cấp sẵn implementation cho một vài phương thức chung được áp dụng cho tất cả các lớp con(subclass).

3. Nếu contract của bạn thay đổi liên tục thì sử dụng interface có thể gặp những vấn đề bởi vì nó không thể thêm những phương thức trong interface mà không thay đổi ở phía class thực hiện implement nó. Với abstract thì bạn không cần lo lắng điều này, do đó trong tình huống này thì sử dụng abstract là một giải pháp hiệu quả.

Cách sử dụng hiệu quả nhất?

Trong thực tế, việc sử dụng cả abstract class và interface là một phương pháp tiếp cận hiệu quả cho việc thiết kế hệ thống. Ví dụ như trong JDK, List là một interface có rất nhiều phương thức, nhưng vẫn có song song một abstract class đó là AbstractList, nó cung cấp những skeletal implementation cho tất cả phương thức của List interface, do đó, mọi subclass có thể extend class này và chỉ implement những phương thức cần thiết.

Chúng ta nên luôn luôn bắt đầu bằng một interface như một base và define những phương thức mà mọi subclasses nên thực hiện và sau đó nếu có một số phương thức mà chỉ subclass nhất định phải implement, chúng ta có thể extend base interface này với các phương thức mới đó. Các subclasses sẽ có tùy chọn để lựa chọn giữa base interface hoặc child interface để thực hiện những yêu cầu của nó. Nếu số lượng phương thức phát triển nên nhiều, ý tưởng mới là sử dụng một abstract class để cung cấp ra bộ khung xương để implement các child interface và cung cấp sự linh hoạt cho các subclass lựa chọn giữa abstract class hoặc interface.

Từ JDK 8 trở đi, bạn có thể có nhiều implement phương thức trong nhiều interface. Tức là bạn có thể tạo ra mặc định như những static phương thức trong những interface và cung cấp implementation cho chúng. Điều này sẽ thu hẹp khoảng cách giữa interface và abstract class, và bây giờ, interface là cách thực hiện tốt nhất. Để biết thêm chi tiết về điểm thay đổi này trên JDK 8, bạn vui lòng đọc tài liệu JDK 8