Menu
CoddyTech

Lớp và phương thức trừu tượng

Thuộc phần Lập trình hướng đối tượng trong hành trình Java của Coddy. Bài học 32 trên 87.

Đôi khi, bạn muốn định nghĩa một lớp làm bản thiết kế nhưng không bao giờ nên tạo đối tượng trực tiếp từ lớp đó. Ví dụ, lớp tổng quát Shape phù hợp làm lớp cha, nhưng một “hình dạng” không có hình thức cụ thể sẽ trông như thế nào? Đây là lúc lớp trừu tượng (abstract class) phát huy tác dụng.

Lớp trừu tượng được khai báo bằng từ khóa abstract và không thể khởi tạo thành đối tượng. Lớp này có thể chứa cả phương thức thông thường có phần triển khai lẫn phương thức trừu tượng không có phần thân:

public abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // Phương thức trừu tượng (abstract method): không có phần triển khai
    public abstract double getArea();
    
    // Phương thức thông thường (regular method): có phần triển khai
    public String getColor() {
        return color;
    }
}

Các phương thức trừu tượng khai báo điều gì mà lớp con phải làm, nhưng không chỉ rõ cách làm. Mọi lớp không trừu tượng kế thừa từ một lớp trừu tượng đều phải cung cấp phần triển khai cho tất cả phương thức trừu tượng:

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Bạn vẫn có thể dùng các lớp trừu tượng làm kiểu tham chiếu, nhờ đó hỗ trợ tính đa hình:

Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea());  // Gọi phần triển khai của Circle

Lớp trừu tượng phù hợp khi các lớp con dùng chung code nhưng phải tự triển khai một số hành vi theo cách khác nhau. Chúng quy định một giao kèo đồng thời cho phép tái sử dụng code.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống thiết bị gia dụng để minh họa sức mạnh của lớp trừu tượng. Bạn sẽ tạo lớp cơ sở Appliance, định nghĩa những việc mọi thiết bị gia dụng phải làm, đồng thời để từng loại thiết bị quyết định cách thực hiện cụ thể.

Bạn sẽ sắp xếp code trong bốn tệp:

  • Appliance.java: Tạo một lớp trừu tượng làm bản thiết kế cho mọi thiết bị gia dụng. Mỗi thiết bị có trường brand (String) và trường wattage (int). Thêm hàm khởi tạo để khởi tạo cả hai trường, các phương thức getter cho từng trường và phương thức thông thường getInfo() trả về: [brand] - [wattage]W. Định nghĩa phương thức trừu tượng operate() mà các lớp con phải triển khai. Phương thức này thể hiện cách mỗi thiết bị thực hiện chức năng chính.
  • WashingMachine.java: Tạo một lớp cụ thể kế thừa Appliance. Máy giặt có thêm trường capacity (int), biểu thị khối lượng đồ giặt tính bằng kg. Dùng super để xử lý việc khởi tạo lớp cha. Triển khai phương thức operate() để in ra: [brand] washing machine is washing [capacity]kg of clothes
  • Microwave.java: Tạo một lớp cụ thể khác kế thừa Appliance. Lò vi sóng có trường power (int), biểu thị phần trăm mức công suất. Triển khai operate() để in ra: [brand] microwave is heating at [power]% power
  • Main.java: Kết hợp mọi thứ bằng tính đa hình. Bạn sẽ nhận năm đầu vào: tên thương hiệu, công suất tính bằng watt, sức chứa của máy giặt, tên một thương hiệu khác và mức công suất của lò vi sóng. Tạo một WashingMachine và một Microwave, sau đó lưu chúng vào một mảng các tham chiếu Appliance. Duyệt qua mảng và với mỗi thiết bị, in thông tin bằng getInfo(), rồi gọi operate().

Bạn sẽ nhận năm đầu vào theo thứ tự sau: thương hiệu thứ nhất (String), công suất thứ nhất tính bằng watt (int), sức chứa tính bằng kg (int), thương hiệu thứ hai (String) và mức công suất (int).

Đầu ra gồm bốn dòng. Với mỗi thiết bị, bạn sẽ thấy dòng thông tin của thiết bị, rồi đến cách thiết bị hoạt động. Hãy chú ý cách lớp trừu tượng giúp bạn xử lý thống nhất các thiết bị khác nhau, trong khi mỗi thiết bị hoạt động theo cách riêng!

Tự làm thử

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Đọc các giá trị đầu vào
        String brand1 = scanner.nextLine();
        int wattage1 = scanner.nextInt();
        int capacity = scanner.nextInt();
        scanner.nextLine(); // Đọc bỏ ký tự xuống dòng
        String brand2 = scanner.nextLine();
        int power = scanner.nextInt();
        
        // TODO: Tạo đối tượng WashingMachine với brand1, wattage1 và capacity
        
        // TODO: Tạo đối tượng Microwave với brand2, wattage1 (hoặc công suất phù hợp) và power
        
        // TODO: Tạo mảng các tham chiếu Appliance và lưu cả hai đối tượng vào mảng
        
        // TODO: Duyệt mảng và với mỗi thiết bị:
        // - In ra thông tin bằng getInfo()
        // - Gọi operate()
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Java online