Java OOP – Interface

Interface trong Java là gì?

Trong Java, một interface là một cách chỉ định hành vi của một lớp bằng cách cung cấp một tập hợp phương thức trừu tượng. Interface là một trong những khái niệm cốt lõi của Java và được sử dụng để đạt được không chỉ tính trừu tượng mà còn tính đa hình và đa kế thừa.

Một số đặc điểm nổi bật của Interface trong Java:

  • Interface không thể được sử dụng để tạo đối tượng.
  • Interface không thể chứa constructor
  • Các phương thức không có thân và thân phương thức được cung cấp bởi lớp triển khai.
  • Các phương thức trong interface được khai báo mặc định là trừu tượng (abstract) và công khai (public) và từ Java 9, bạn có thể khai báo phương thức private trong interface.
  • Với bản thấp hơn Java 8, khi triển khai một interface, tất cả các phương thức trong interface đó phải được ghi đè. Tuy nhiên, tại bản Java 8 giới thiệu phương thức mặc định (default method) cho phép b
  • Các thuộc tính trong interface được khai báo mặc định là công khai (public), tĩnh (static) và không thay đổi (final).

Mục đích sử dụng Interface trong Java

Interface trong Java được sử dụng để đạt một số mục đích chính sau:

Một số mục đích sử dụng Interface trong Java
Một số mục đích sử dụng Interface trong Java

Tính trừu tượng hoàn toàn

Trừu tượng hoàn toàn là khái niệm quan trọng trong lập trình hướng đối tượng. Tính trừu tượng hoàn toàn của interface chỉ định các phương thức hoặc các hành động mà một đối tượng có thể thực hiện mà không quan tâm đến cách thức thực hiện của chúng. Nó cho phép các đối tượng được tách biệt hoàn toàn với nhau và đảm bảo tính tương thích giữa các đối tượng khác nhau.

Đa kế thừa

Java không hỗ trợ đa kế thừa, nhưng sử dụng interface, bạn có thể đạt được đa kế thừa. Việc này cho phép một lớp triển khai nhiều interface và sử dụng các phương thức được định nghĩa trong các interface đó. Tính năng này giúp giảm sự lặp lại mã và tăng tính tái sử dụng trong lập trình hướng đối tượng.

Tính đa hình

Tính đa hình trong lập trình là khả năng của đối tượng để thực thi các phương thức khác nhau tùy thuộc vào loại đối tượng cụ thể mà nó đang tham chiếu đến trong runtime. Trong Java, chúng ta có thể đạt được tính đa hình bằng cách sử dụng các interface để triển khai các phương thức khác nhau cho các lớp khác nhau.

Kết nối lỏng (Loose Coupling)

Thuật ngữ Coupling (kết nối) mô tả sự phụ thuộc của một lớp vào lớp khác. Vì vậy, khi sử dụng một interface, chúng ta định nghĩa các phương thức và chữ ký (method signature) của chúng một cách độc lập. Như vậy, tất cả các phương thức và lớp đều hoàn toàn độc lập, không phụ thuộc vào nhau, từ đó đạt được Loose Coupling (kết nối lỏng).

Một số thao tác cơ bản của Interface trong Java

Dưới đây là một số thao tác cơ bản với Interface trong Java:

Khai báo Interface (Declare)

Để khai báo Interface trong Java chúng ta sử dụng cú pháp sau:

[access modifier] interface <tên Interface> [extends SuperInterface1, SuperInterface2, …] {
// Khai báo phương thức và biến trong Interface

}

Trong đó:

  • Access modifier: chỉ phạm vi truy cập của interface, gồm public, default hoặc private (Java 9)
  • SuperInterface1, SuperInterface2,… là danh sách các interface mà interface hiện tại được kế thừa (nếu có)

Trong một interface, chúng ta được phép khai báo:

  • Biến, hằng số
  • Phương thức trừu tượng (abstract method)
  • Phương thức static (static method)
  • Phương thức mặc định (default method) hỗ trợ từ Java 8

Triển khai Interface (Implement)

Khi một lớp triển khai một interface, bạn có thể coi lớp đó như đang ký hợp đồng, đồng ý thực hiện các hành vi cụ thể của interface. Nếu một lớp không thực hiện tất cả các hành vi của interface, lớp đó phải khai báo mình là abstract.

Một lớp sử dụng từ khóa “implements” để triển khai một interface. Từ khóa “implements” xuất hiện trong khai báo lớp sau phần “extends” của khai báo.

Ví dụ:

// Khai báo interface
public interface Printable {

    void print();

}

// Triển khai interface

public class Document implements Printable {

    public void print() {

        System.out.println(“Printing a document…”);

    }

}

// Sử dụng đối tượng triển khai interface

public class Main {

    public static void main(String[] args) {

        Printable obj = new Document();

        obj.print(); // Output: Printing a document…

    }

}

Trong ví dụ này, interface Printable định nghĩa một phương thức print(). Lớp Document triển khai interface này bằng cách cung cấp một cài đặt cho phương thức này. Trong phương thức print() của Document, ta đơn giản in ra một thông báo.

Mở rộng Interfaces (Extends)

Một interface có thể mở rộng một interface khác giống như một lớp có thể mở rộng một lớp khác. Từ khóa “extends” được sử dụng để mở rộng một interface, và interface con kế thừa các phương thức của interface cha.

// Khai báo interface cha
public interface Animal {

    void eat();

}

// Khai báo interface con mở rộng interface cha

public interface Cat extends Animal {

    void play();

Trong ví dụ này, interface Animal định nghĩa phương thức eat(). Interface Cat mở rộng Animal và định nghĩa thêm một phương thức play(). Bằng cách này, khi bạn triển khai interface Cat, bạn sẽ cần cung cấp cả hai phương thức eat() và play().

Mở rộng nhiều Interfaces

Một lớp Java chỉ có thể mở rộng một lớp cha. Đa thừa kế không được phép. Tuy nhiên, các interface không phải là các lớp và một interface có thể mở rộng nhiều hơn một interface cha. Từ khóa “extends” được sử dụng một lần, và các interface cha được khai báo trong một danh sách phân tách bằng dấu phẩy.

Nếu ví dụ phía trên có 1 interface cha là Animal và 1 interface con là Cat, tại đây chúng ta thêm 1 interface là Earth thì chúng ta sẽ viết như sau:

public interface Cat extends Animal, Earth 

Đánh dấu Interface (Tagging)

Trong Java, đánh dấu một lớp hoặc interface là một cách để chỉ định rằng lớp hoặc interface đó có chức năng gì đó đặc biệt. Ví dụ, interface Serializable được sử dụng để chỉ định rằng một đối tượng có thể được chuyển đổi thành một dạng dữ liệu có thể lưu trữ hoặc chuyển qua mạng. Việc đánh dấu interface là một cách để cung cấp cho trình biên dịch hoặc các công cụ khác thông tin về tính chất của một đối tượng hoặc lớp

Ví dụ:

package java.io;public interface Serializable {}

Mục đích đánh dấu interface là để:

  • Để tạo một interface cha chung giữa các interface có liên quan và thêm một kiểu dữ liệu vào một lớp.
  • Thêm một kiểu dữ liệu vào một lớp. Một lớp khi triển khai một interface đánh dấu không cần phải định nghĩa bất kỳ phương thức nào (vì interface không có phương thức), nhưng lớp đó trở thành một kiểu interface thông qua đa hình.

Mối quan hệ giữa lớp và interface trong Java

Lớp có thể triển khai một hoặc nhiều interface để định nghĩa các phương thức mà lớp đó cần phải cài đặt. Interface chỉ định nghĩa các phương thức mà các lớp triển khai phải cài đặt. Như được hiển thị trong hình dưới đây, một lớp kế thừa từ một lớp khác, một giao diện kế thừa từ một giao diện khác và một lớp triển khai một interface.

Mối quan hệ giữa lớp và interface trong Java