Abstract Class: "Sườn" cho Gen Z, OOP Java Explained!
Java – OOP

Abstract Class: "Sườn" cho Gen Z, OOP Java Explained!

Author

Admin System

@root

Ngày xuất bản

18 Mar, 2026

Lượt xem

1 Lượt

Abstract Class

Chào các "coder nhí" tương lai và hiện tại của anh Creyt! Hôm nay, chúng ta sẽ "đập hộp" một khái niệm mà nhiều bạn trẻ hay "nhức cái đầu" trong OOP Java: Abstract Class. Nghe tên có vẻ "trừu tượng" nhưng thực ra nó "thực tế" đến không ngờ, giống như việc bạn lên kế hoạch đi chơi nhưng chưa chốt địa điểm vậy.

1. Abstract Class là gì? "Sườn" nhà chưa xong nhưng đã có phong thủy!

Trong thế giới lập trình, đặc biệt là với Java và OOP, Abstract Class không phải là một cái gì đó quá xa vời. Anh Creyt hay ví von nó như một bản thiết kế kiến trúc sư đã có sườn chính, có layout cơ bản, nhưng chưa hoàn thiện để ở ngay được. Tức là, nó định hình một cấu trúc chung, một "khuôn mẫu" cho một nhóm các đối tượng liên quan, nhưng bản thân nó lại không thể tự mình tạo ra một đối tượng hoàn chỉnh (instantiate) được.

Để làm gì? Đơn giản là để:

  • Định nghĩa một "hợp đồng" chung: Nó nói với các lớp con của nó rằng: "Này các con, đây là những việc các con phải làm (abstract methods) và đây là những việc các con có thể dùng chung với bố (concrete methods)."
  • Cung cấp một phần cài đặt mặc định: Không phải mọi thứ đều phải làm lại từ đầu. Abstract Class có thể cung cấp sẵn một số phương thức đã được triển khai, giúp các lớp con đỡ phải viết lại code.
  • Thúc đẩy tính kế thừa và đa hình (Polymorphism): Nó là một "người cha" tuyệt vời để các "con" của nó (subclasses) thừa hưởng và phát triển theo cách riêng, nhưng vẫn nằm trong khuôn khổ gia đình.

Dễ hiểu hơn: Tưởng tượng bạn có một Abstract Class tên là Animal. Animal có thể có một phương thức abstractmakeSound() (vì mỗi con vật kêu khác nhau, chó sủa, mèo kêu meo meo) và một phương thức concreteeat() (vì con vật nào cũng ăn). Bạn không thể tạo ra một new Animal() vì "con vật" chung chung thì làm sao mà kêu được? Phải là new Dog() hoặc new Cat() thì mới có tiếng kêu cụ thể chứ!

2. Code Ví Dụ: "Sườn" nhà lên code

Để các bạn Gen Z không "bay màu" giữa biển lý thuyết, anh Creyt sẽ "show hàng" ngay một ví dụ code "sắc nét" để các bạn thấy rõ Abstract Class hoạt động như thế nào.

// Bước 1: Định nghĩa một Abstract Class
abstract class Shape {
    // Đây là một phương thức abstract (trừu tượng)
    // Nó không có phần thân, chỉ có chữ ký (signature).
    // Các lớp con BẮT BUỘC phải triển khai phương thức này.
    public abstract double calculateArea();

    // Đây là một phương thức concrete (cụ thể)
    // Nó có phần thân và được triển khai ngay trong lớp abstract.
    // Các lớp con có thể sử dụng trực tiếp hoặc ghi đè (override) nó.
    public void displayInfo() {
        System.out.println("Đây là một hình dạng.");
    }

    // Constructor cũng có thể có trong abstract class
    public Shape() {
        System.out.println("Một hình dạng đã được tạo.");
    }
}

// Bước 2: Tạo một lớp con kế thừa Abstract Class
class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        super(); // Gọi constructor của lớp cha
        this.radius = radius;
    }

    // BẮT BUỘC phải triển khai phương thức abstract calculateArea()
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }

    // Có thể ghi đè phương thức concrete của lớp cha nếu muốn
    @Override
    public void displayInfo() {
        System.out.println("Đây là hình tròn với bán kính: " + radius);
    }
}

// Bước 3: Tạo một lớp con khác kế thừa Abstract Class
class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        super();
        this.width = width;
        this.height = height;
    }

    // BẮT BUỘT phải triển khai phương thức abstract calculateArea()
    @Override
    public double calculateArea() {
        return width * height;
    }

    // Không ghi đè displayInfo(), nên sẽ dùng của lớp cha
}

// Bước 4: Lớp để chạy và kiểm tra
public class AbstractClassDemo {
    public static void main(String[] args) {
        // KHÔNG THỂ tạo đối tượng từ Abstract Class trực tiếp
        // Shape myShape = new Shape(); // Lỗi biên dịch!

        Circle circle = new Circle(5);
        System.out.println("Diện tích hình tròn: " + circle.calculateArea());
        circle.displayInfo(); // Dùng phương thức đã override

        System.out.println("------------------");

        Rectangle rectangle = new Rectangle(4, 6);
        System.out.println("Diện tích hình chữ nhật: " + rectangle.calculateArea());
        rectangle.displayInfo(); // Dùng phương thức mặc định của lớp cha

        // Ví dụ về tính đa hình (Polymorphism) với Abstract Class
        Shape s1 = new Circle(3);
        Shape s2 = new Rectangle(2, 5);

        System.out.println("------------------");
        System.out.println("Diện tích s1 (Circle): " + s1.calculateArea());
        System.out.println("Diện tích s2 (Rectangle): " + s2.calculateArea());
    }
}

Output của đoạn code trên sẽ là:

Một hình dạng đã được tạo.
Diện tích hình tròn: 78.53981633974483
Đây là hình tròn với bán kính: 5.0
------------------
Một hình dạng đã được tạo.
Diện tích hình chữ nhật: 24.0
Đây là một hình dạng.
------------------
Một hình dạng đã được tạo.
Một hình dạng đã được tạo.
Diện tích s1 (Circle): 28.27433388230813
Diện tích s2 (Rectangle): 10.0

Thấy chưa, Shape là một cái khung, các lớp con CircleRectangle mới là những "ngôi nhà" thực sự được xây dựng trên cái khung đó, mỗi ngôi nhà có cách tính diện tích riêng nhưng đều tuân thủ nguyên tắc "phải có diện tích" của Shape.

Illustration

3. Mẹo "hack não" và Best Practices từ anh Creyt

  • Ghi nhớ "bắt buộc": Nếu một lớp có bất kỳ phương thức abstract nào, thì lớp đó phải được khai báo là abstract. Ngược lại, một lớp abstract có thể không có phương thức abstract nào (nhưng thường thì có). Mẹo: "Đã là cha trừu tượng thì con phải có trách nhiệm."
  • Không thể "new" trực tiếp: Bạn không thể tạo đối tượng từ một Abstract Class. Nó giống như bạn không thể "mua" một bản thiết kế nhà để ở vậy. Bạn phải xây nhà từ bản thiết kế đó.
  • Kế thừa là chìa khóa: Abstract Class được thiết kế để được kế thừa. Lớp con đầu tiên không abstract mà kế thừa nó bắt buộc phải triển khai tất cả các phương thức abstract của lớp cha.
  • Một chiều: Một lớp con chỉ có thể kế thừa một Abstract Class (Java không hỗ trợ đa kế thừa lớp). Nhưng nó có thể triển khai nhiều interface.
  • Khi nào dùng Abstract Class, khi nào dùng Interface?
    • Abstract Class: Dùng khi bạn có một mối quan hệ "is-a" mạnh mẽ (ví dụ: Circle IS-A Shape), muốn cung cấp một số triển khai mặc định, và muốn các lớp con chia sẻ trạng thái (fields) hoặc hành vi chung. Nó giống như một "người cha" có thể cho con một ít tiền tiêu vặt (concrete methods) và bắt con tự kiếm tiền (abstract methods).
    • Interface: Dùng khi bạn chỉ muốn định nghĩa một "hợp đồng" thuần túy, không có bất kỳ triển khai nào. Nó giống như một "bản cam kết" mà bất kỳ ai ký vào cũng phải tuân thủ, không cần biết họ là ai hay họ có gì.

4. Học thuật sâu từ Harvard (mà vẫn dễ hiểu)

Từ góc độ học thuật, Abstract Class là một công cụ mạnh mẽ trong việc thiết kế kiến trúc phần mềm hướng đối tượng, đặc biệt là trong việc hiện thực hóa nguyên tắc Open/Closed Principle (OCP) của SOLID. Nó cho phép hệ thống của bạn mở rộng (Open for extension) bằng cách thêm các lớp con mới mà không cần sửa đổi (Closed for modification) các lớp hiện có.

Nó cũng là nền tảng cho Polymorphism (đa hình), cho phép chúng ta xử lý các đối tượng thuộc các lớp con khác nhau thông qua một tham chiếu của lớp cha abstract. Điều này tạo ra một mã nguồn linh hoạt, dễ bảo trì và mở rộng, nơi các chi tiết cụ thể của việc triển khai được "đẩy" xuống các lớp con, trong khi giao diện chung được giữ vững ở lớp cha. Đây chính là xương sống của việc xây dựng các hệ thống mô-đun và có khả năng thích ứng cao.

5. Ứng dụng thực tế: "Abstract Class" ở đâu trong thế giới số?

Bạn có thể thấy Abstract Class "ẩn mình" trong rất nhiều ứng dụng và framework mà bạn dùng hàng ngày:

  • Java Collections Framework: Các lớp như AbstractList, AbstractSet, AbstractMap là những ví dụ kinh điển. Chúng cung cấp các triển khai cơ bản cho các interface tương ứng (như List, Set, Map), giúp các nhà phát triển tạo ra các kiểu danh sách, tập hợp, bản đồ tùy chỉnh mà không cần viết lại toàn bộ code.
  • Game Engines: Trong một game engine, bạn có thể có một abstract class GameObject với các phương thức abstract update()render(). Các lớp con như Player, Enemy, NPC, Item sẽ kế thừa GameObject và triển khai cách chúng tự cập nhật trạng thái hoặc hiển thị trên màn hình.
  • Framework UI/UX: Các framework như Swing hay JavaFX thường sử dụng Abstract Class cho các thành phần UI cơ bản. Ví dụ, một abstract class Component có thể định nghĩa các hành vi chung như repaint() nhưng để các lớp con như Button, TextField tự định nghĩa cách chúng được vẽ ra.
  • Payment Gateways: Một hệ thống thanh toán có thể có abstract class PaymentGateway với phương thức abstract processPayment(). Các lớp con như CreditCardPaymentGateway, PayPalGateway, VNPayGateway sẽ triển khai logic xử lý thanh toán cụ thể cho từng phương thức.

6. Thử nghiệm và hướng dẫn nên dùng cho case nào

Thử nghiệm đã từng: Anh Creyt từng thấy nhiều bạn newbie "vung tay quá trán" khi dùng Abstract Class, cố gắng nhét đủ thứ vào đó, hoặc ngược lại, biến mọi thứ thành Abstract Class khi chỉ cần một interface đơn giản là đủ. Sai lầm phổ biến là cố gắng tạo đối tượng từ Abstract Class, hoặc quên mất không triển khai tất cả các phương thức abstract ở lớp con.

Nên dùng cho case nào?

  • Khi bạn muốn cung cấp một bản thiết kế chung: Giả sử bạn đang xây dựng một hệ thống quản lý nhân sự. Bạn có thể có một abstract class Employee với các thuộc tính chung như name, id, salary và một phương thức abstract calculateBonus(). Các lớp con như FullTimeEmployeePartTimeEmployee sẽ có cách tính bonus khác nhau nhưng đều phải tính bonus.
  • Khi bạn muốn ép buộc các lớp con phải có một hành vi nhất định: Nếu tất cả các loại Vehicle (xe cộ) trong hệ thống của bạn đều phải có khả năng start()stop(), nhưng cách start()stop() của Car khác Motorcycle, thì abstract class Vehicle là lựa chọn tuyệt vời với các phương thức abstract start()stop().
  • Khi bạn muốn chia sẻ code giữa các lớp con: Nếu các lớp con có nhiều logic chung (ví dụ: cách ghi log, cách quản lý ID), bạn có thể đặt chúng vào các phương thức concrete trong Abstract Class để tránh lặp code.

Nhớ nhé, Abstract Class không chỉ là một khái niệm khô khan trong sách vở, nó là một công cụ mạnh mẽ giúp bạn xây dựng những hệ thống phần mềm "ngon lành cành đào" hơn, dễ quản lý và mở rộng hơn. Hãy "combat" nhiệt tình với nó, và bạn sẽ thấy thế giới OOP rộng lớn đến nhường nào! Chúc các bạn code vui!

Thuộc Series: Java – OOP

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!