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 CircleLớ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.
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ườngbrand(String) và trườngwattage(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ườnggetInfo()trả về:[brand] - [wattage]W. Định nghĩa phương thức trừu tượngoperate()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ườngcapacity(int), biểu thị khối lượng đồ giặt tính bằng kg. Dùngsuperđể xử lý việc khởi tạo lớp cha. Triển khai phương thứcoperate()để in ra:[brand] washing machine is washing [capacity]kg of clothesMicrowave.java: Tạo một lớp cụ thể khác kế thừa Appliance. Lò vi sóng có trườngpower(int), biểu thị phần trăm mức công suất. Triển khaioperate()để in ra:[brand] microwave is heating at [power]% powerMain.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ếuAppliance. Duyệt qua mảng và với mỗi thiết bị, in thông tin bằnggetInfo(), rồi gọioperate().
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()
}
}
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
1Kiến thức cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcTrường (thuộc tính)Phương thức khởi tạoNạp chồng phương thức khởi tạoÔn tập: Máy tính đơn giản4Kế thừa
Kế thừa cơ bản (extends)Từ khóa superGhi đè phương thức (@Override)Chuỗi gọi hàm khởi tạoLớp ObjectKế thừa đơn và đa cấpVì sao không hỗ trợ kế thừa nhiều lớpÔn tập: Phân cấp lớp Employee7Phương thức đặc biệt và lớp Object
Phương thức toString()equals() và hashCode()Phương thức clone()compareTo() và ComparableGiao diện ComparatorÔn tập: sắp xếp tùy chỉnh2Bộ điều chỉnh quyền truy cập và đóng gói
Tổng quan về các mức truy cậpPhương thức getter và setterẨn thông tinTừ khóa finalÔn tập: Trình quản lý tài khoản ngân hàng5Tính đa hình
Kiến thức cơ bản về nạp chồng phương thứcGhi đè phương thức (thời gian chạy)Chuyển kiểu lên và chuyển kiểu xuốngToán tử instanceofLớp và phương thức trừu tượngÔn tập: máy tính hình học8Khái niệm OOP nâng cao
Kết hợp và kế thừaKết tập và hợp thànhLớp bên trong, lớp lồng nhau và lớp ẩn danhKiểu enum và phương thức enumBản ghi (Java 16+)Lớp sealed (Java 17+)3Thuộc tính lớp và thành viên tĩnh
Biến của instance và biến tĩnhPhương thức tĩnhKhối tĩnhHằng số (static final)Ôn tập: bộ đếm và tiện ích6Giao diện và lớp trừu tượng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnPhương thức mặc định và tĩnh trong giao diệnLớp trừu tượng và giao diệnGiao diện hàmÔn tập: hệ thống thanh toán9Kiểu tổng quát
Giới thiệu về kiểu tổng quátLớp tổng quátPhương thức tổng quátTham số kiểu có giới hạnKý tự đại diện (?, extends, super)Ôn tập: vùng chứa tổng quát12Mẫu thiết kế, phần 2
Mẫu CommandMẫu AdapterMẫu DecoratorMẫu Template MethodMẫu StateMẫu CompositeMẫu IteratorTự luyện tập: Trình biên dịch Java online