CodeGym /Các khóa học /JAVA 25 SELF /Sự khác nhau giữa interface và abstract class

Sự khác nhau giữa interface và abstract class

JAVA 25 SELF
Mức độ, Bài học
Có sẵn

1. Abstract class: ôn lại cơ bản

Trước khi đi vào so sánh, hãy nhắc lại abstract class là gì.

Abstract class — là một class không thể tạo instance trực tiếp (không thể viết new Animal()), nhưng có thể chứa cả phương thức thông thường (đã có triển khai) lẫn phương thức abstract (chưa có triển khai). Abstract class thường được dùng làm nền tảng cho các class khác kế thừa hành vi của nó và/hoặc buộc phải triển khai một số phương thức.

Ví dụ, nếu trong ứng dụng của chúng ta có nhiều loại phương tiện, ta có thể tạo một abstract class Transport:

public abstract class Transport {
    private String model;

    public Transport(String model) {
        this.model = model;
    }

    public String getModel() {
        return model;
    }

    // Phương thức abstract — không có triển khai, chỉ khai báo
    public abstract void move();

    // Phương thức thông thường — có triển khai
    public void printInfo() {
        System.out.println("Mẫu phương tiện: " + model);
    }
}

Đặc điểm của abstract class:

  • Có thể chứa field (trạng thái).
  • Có thể chứa các phương thức đã được triển khai.
  • Có thể chứa các phương thức abstract (bắt buộc các lớp con phải triển khai).
  • Không thể tạo instance trực tiếp.
  • Dùng để chia sẻ hành vi và trạng thái chung.

2. Interface: ôn lại cơ bản

Interface — là tập hợp các phương thức mà một class phải triển khai. Interface không mô tả trạng thái (không có field thông thường, chỉ có hằng số), và không chứa phần triển khai phương thức (trước Java 8). Interface là một bản hợp đồng thuần túy: “Nếu bạn triển khai tôi, bạn bắt buộc phải làm được những việc này”.

Ví dụ về interface:

public interface Movable {
    void move(int x, int y);
}

Đặc điểm của interface:

  • Không chứa trạng thái (chỉ có public static final hằng số).
  • Trước Java 8 — chỉ có các phương thức abstract (từ Java 8 xuất hiện phương thức default và static, sẽ nói sau).
  • Mặc định, các phương thức luôn là public abstract.
  • Một class có thể triển khai nhiều interface.
  • Dùng để mô tả khả năng — “class có thể làm gì”.

3. Bảng so sánh: abstract class vs interface

Đã đến lúc so sánh trực diện hai công cụ này! Dưới đây là bảng trực quan:

Đặc điểm Abstract class Interface
Cú pháp
abstract class
interface
Có thể tạo instance? Không Không
Có thể có phương thức thông thường? Có Trước Java 8 — không; từ Java 8 — chỉ default/static
Có thể có phương thức abstract? Có Có (trước Java 8, tất cả các phương thức đều là abstract)
Có thể có field (trạng thái)? Có (bất kỳ field nào) Chỉ public static final (hằng số)
Có thể có constructor? Có Không
Kế thừa Chỉ một class (abstract hoặc thường) Có thể triển khai nhiều interface
Modifier của phương thức Bất kỳ (public, protected, private) Mặc định phương thức là public abstract. Từ Java 9 có thể thêm phương thức private để dùng bên trong interface
Kế thừa/triển khai qua
extends
implements
Thường dùng để làm gì Chung phần triển khai và trạng thái Mô tả khả năng, vai trò
Ví dụ trong JDK
AbstractList, AbstractMap
Comparable, Runnable

4. Khi nào dùng interface, khi nào dùng abstract class?

Interface dùng khi:

  • Bạn muốn mô tả “class làm được gì” mà không quan tâm nó làm thế nào.
  • Bạn cần class có thể triển khai nhiều khả năng độc lập.
  • Ví dụ: Comparable (có thể so sánh), Serializable (có thể tuần tự hóa), Runnable (có thể chạy trong thread).

Abstract class dùng khi:

  • Bạn muốn đặt ra phần triển khai và trạng thái chung cho mọi lớp con.
  • Bạn cần tất cả lớp con có những field nhất định hoặc các phương thức đã được triển khai.
  • Kế thừa — nghiêm ngặt “một-một”: class chỉ có thể kế thừa một class (thường hoặc abstract).

Ẩn dụ đời sống

  • Interface — giống như “giấy phép lái xe”: nếu bạn có nó, bạn có thể lái xe, nhưng không ai nói bạn lái chiếc nào và cách bạn lái ra sao.
  • Abstract class — giống như “bản thiết kế chung của ô tô”: mọi xe đều có vô lăng, bàn đạp, động cơ, nhưng mỗi hãng sẽ hiện thực chi tiết theo cách riêng.

5. Ví dụ từ thư viện chuẩn Java

Interface: Comparable

public interface Comparable<T> {
    int compareTo(T o);
}

Bất kỳ class nào triển khai interface này đều phải triển khai phương thức compareTo. Ví dụ: String, Integer, LocalDate và nhiều lớp khác.

Abstract class: AbstractList

public abstract class AbstractList<E> implements List<E> {
    // Triển khai mặc định một số phương thức của List
    // Một số phương thức được để ở dạng abstract
}

AbstractList đã triển khai sẵn một phần hành vi của các collection (ví dụ, các phương thức thêm/xóa), nhưng để lại một số phương thức ở dạng abstract để các lớp con có thể hiện thực theo cách của mình.

6. Ví dụ mã: so sánh trong thực tế

Interface

Tạo một interface và một class triển khai nó.

public interface Printable {
    void print();
}

public class Document implements Printable {
    @Override
    public void print() {
        System.out.println("Đang in tài liệu...");
    }
}

Abstract class

Bây giờ là abstract class và lớp con của nó.

public abstract class Machine {
    public void turnOn() {
        System.out.println("Máy đã bật.");
    }

    public abstract void work();
}

public class Printer extends Machine {
    @Override
    public void work() {
        System.out.println("Máy in đang in...");
    }
}

Một class vừa kế thừa abstract class vừa triển khai interface

public class SmartPrinter extends Machine implements Printable {
    @Override
    public void work() {
        System.out.println("Máy in thông minh đang hoạt động...");
    }

    @Override
    public void print() {
        System.out.println("Máy in thông minh đang in...");
    }
}

7. Triển khai nhiều interface: vì sao điều này hữu ích

Trong Java, một class chỉ có thể kế thừa một class (abstract hoặc thường), nhưng có thể triển khai bao nhiêu interface tùy ý! Điều này cho phép tạo ra kiến trúc linh hoạt và dễ mở rộng.

public interface Scannable {
    void scan();
}

public class MultiFunctionPrinter extends Machine implements Printable, Scannable {
    @Override
    public void work() {
        System.out.println("Máy đa chức năng đang hoạt động...");
    }

    @Override
    public void print() {
        System.out.println("Máy đa chức năng đang in...");
    }

    @Override
    public void scan() {
        System.out.println("Máy đa chức năng đang quét...");
    }
}

Khi nào chọn cái nào?

  • Nếu bạn thiết kế chức năng nền tảng có trạng thái chung (ví dụ: field), hãy dùng abstract class.
  • Nếu bạn muốn gắn cho đối tượng các “nhãn khả năng” (ví dụ: “có thể in”, “có thể so sánh”, “có thể tuần tự hóa”) — hãy dùng interface.
  • Nếu chưa chắc chắn — hãy bắt đầu với interface. Trong Java đây là thói quen tốt: interface mang lại tính linh hoạt và khả năng mở rộng cao.

8. Lỗi thường gặp và điểm cần lưu ý

Lỗi số 1: Cố gắng kế thừa nhiều class — Java sẽ không cho phép!
Class chỉ có thể kế thừa một class, nhưng có thể triển khai nhiều interface. Ví dụ, class A extends B, C — lỗi, còn class A extends B implements X, Y, Z — thì được.

Lỗi số 2: Nhầm lẫn giữa field của interface và của class.
Trong interface, chỉ có thể khai báo hằng số (public static final). Không thể khai báo trạng thái thông thường, ví dụ private int count; — compiler sẽ chặn ngay.

Lỗi số 3: Không triển khai tất cả phương thức của interface.
Nếu class không triển khai dù chỉ một phương thức của interface — nó phải được khai báo là abstract, nếu không compiler sẽ báo lỗi.

Lỗi số 4: Cố tạo instance của interface hoặc abstract class.
Cả hai loại này đều là “bán thành phẩm”. Chỉ có thể mở rộng, không thể tạo trực tiếp:

Printable p = new Printable(); // Lỗi!
Machine m = new Machine();     // Lỗi!

Lỗi số 5: Nghĩ rằng interface có thể có constructor.
Interface không thể có constructor vì chúng không mô tả trạng thái của đối tượng. Chỉ class (thường và abstract) mới có.

1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Công ty Vận tải: Giao thức thống nhất cho chuyển động
Công ty Vận tải: Giao thức thống nhất cho chuyển động
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Sổ đăng ký Đại học: Cá nhân và Mã định danh
Sổ đăng ký Đại học: Cá nhân và Mã định danh
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Thiết bị đa chức năng văn phòng
Thiết bị đa chức năng văn phòng
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Điện thoại thông minh: Từ thiết bị chung đến thiết bị cá nhân
Điện thoại thông minh: Từ thiết bị chung đến thiết bị cá nhân
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION