Menu
CoddyTech

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 Dart của Coddy. Bài học 44 trên 110.

Phương thức trừu tượng là phương thức được khai báo bên trong một lớp trừu tượng nhưng không có phần thân. Phương thức này định nghĩa chữ ký phương thức nhưng để mỗi lớp con tự triển khai. Bất kỳ lớp nào kế thừa lớp trừu tượng đều phải ghi đè tất cả các phương thức trừu tượng, nếu không lớp đó cũng sẽ là lớp trừu tượng.

abstract class Animal {
  // Phương thức trừu tượng (abstract method): không có thân, các lớp con phải triển khai
  String makeSound();

  // Phương thức cụ thể (concrete method): có thân, dùng chung cho mọi lớp con
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  @override
  String makeSound() {
    return 'Woof!';  // Phải triển khai phương thức này
  }
}

class Cat extends Animal {
  @override
  String makeSound() {
    return 'Meow!';  // Cách triển khai khác nhau, cùng chữ ký
  }
}

Nếu một lớp con quên triển khai phương thức trừu tượng, Dart sẽ báo lỗi biên dịch. Đây chính là mục đích: phương thức trừu tượng đảm bảo tuân thủ một giao ước. Mọi lớp con đều chắc chắn có phương thức đó, vì vậy bạn có thể an tâm gọi phương thức này trên bất kỳ đối tượng nào thuộc kiểu trừu tượng.

// Bạn có thể dùng kiểu trừu tượng làm kiểu dữ liệu cho biến.
Animal a = Dog();
print(a.makeSound());  // Gâu!

Animal b = Cat();
print(b.makeSound());  // Meo!

Phương thức trừu tượng khác với phương thức cụ thể trong lớp trừu tượng. Phương thức cụ thể có phần thân và được kế thừa nguyên vẹn. Phương thức trừu tượng không có phần thân và phải được ghi đè.

Bạn có thể kết hợp cả hai trong cùng một lớp trừu tượng để chia sẻ một số hành vi, đồng thời buộc các lớp con tự định nghĩa hành vi cho những phần còn lại.

Đặc điểmPhương thức trừu tượngPhương thức cụ thể
Có thân hàmKhôngCó
Bắt buộc ghi đèCóKhông
Mục đíchĐảm bảo hợp đồngChia sẻ hành vi
Phạm viChỉ trong lớp trừu tượngBất kỳ lớp nào
challenge icon

Thử thách

Dễ

Hãy xây dựng một chương trình tính toán hình dạng để minh họa cách các phương thức trừu tượng hoạt động. Bạn sẽ định nghĩa một lớp trừu tượng với các phương thức trừu tượng mà mỗi hình dạng phải tự triển khai theo cách riêng, rồi sử dụng các hình dạng đó thông qua một giao diện chung.

Bạn sẽ tổ chức code thành bốn tệp:

  • shape.dart: Định nghĩa lớp trừu tượng Shape với trường final color (String) và hàm khởi tạo để khởi tạo trường này. Khai báo hai phương thức trừu tượng: double area() và double perimeter(). Thêm một phương thức cụ thể describe() để in ra A [color] shape with area: [area] and perimeter: [perimeter]. Vì area() và perimeter() là các phương thức trừu tượng, mỗi lớp con sẽ cung cấp cách tính riêng, nhưng describe() dùng được cho tất cả mà không cần ghi đè.
  • circle.dart: Tạo lớp Circle kế thừa Shape. Lớp này có trường final radius (double). Hàm khởi tạo nhận color và radius, rồi truyền color cho super. Triển khai area() để trả về 3.14 * radius * radius và perimeter() để trả về 2 * 3.14 * radius.
  • rectangle.dart: Tạo lớp Rectangle kế thừa Shape. Lớp này có các trường final width và height (đều là double). Hàm khởi tạo nhận color, width và height, rồi truyền color cho super. Triển khai area() để trả về width * height và perimeter() để trả về 2 * (width + height).
  • main.dart: Nhập tất cả các tệp. Tạo một Circle có màu 'red' và bán kính 5.0, cùng một Rectangle có màu 'blue', chiều rộng 4.0 và chiều cao 6.0. Gọi describe() cho mỗi hình dạng. Sau đó, tạo một List<Shape> chứa cả hai hình dạng, duyệt qua danh sách và in ra Area: [area] cho mỗi hình dạng.

Đầu ra dự kiến:

A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0

Tự làm thử

import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';

void main() {
  // TODO: Tạo một Circle có màu 'red' và bán kính 5.0

  // TODO: Tạo một Rectangle có màu 'blue', chiều rộng 4.0 và chiều cao 6.0

  // TODO: Gọi describe() trên hình tròn

  // TODO: Gọi describe() trên hình chữ nhật

  // TODO: Tạo một List<Shape> chứa cả hai hình

  // TODO: Duyệt qua danh sách và in ra "Area: [area]" cho mỗi hình
}
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 Dart online