Dart 中的抽象类
最后修改于 2025 年 5 月 25 日
本教程探讨 Dart 中的抽象类,这是创建类层次结构和定义接口的关键功能。抽象类能够实现多态和代码重用,同时强制执行实现契约。
抽象类概述
Dart 中的抽象类是无法直接实例化的不完整蓝图。它们定义了一个具体子类必须实现的契约。抽象类可以包含已实现的方法和抽象方法的声明。
与普通类不同,抽象类可以包含未实现的方法(抽象方法)。任何具体的(非抽象)子类都必须实现这些方法。抽象类使用 abstract
修饰符声明。
功能 | 抽象类 | 普通类 |
---|---|---|
实例化 | 不能实例化 | 可以实例化 |
方法 | 可以包含抽象方法 | 所有方法都已实现 |
目的 | 定义接口/行为 | 完整实现 |
继承 | 必须继承 | 可直接使用 |
当您想在多个相关类之间共享代码,同时强制执行某些方法的实现时,抽象类特别有用。它们介于接口(纯契约)和具体类(完整实现)之间。
基本抽象类
本示例演示了一个具有具体方法和抽象方法的简单抽象类。我们将创建一个抽象的 Shape
类,它为所有形状定义了通用行为。
abstract class Shape { // Abstract method (no implementation) double area(); // Concrete method void describe() { print('This shape has an area of ${area()}'); } } class Circle extends Shape { final double radius; Circle(this.radius); @override double area() => 3.14159 * radius * radius; } class Square extends Shape { final double side; Square(this.side); @override double area() => side * side; } void main() { // var shape = Shape(); // Error: Can't instantiate abstract class var circle = Circle(5.0); var square = Square(4.0); circle.describe(); square.describe(); }
Shape
抽象类声明了一个抽象的 area
方法,子类必须实现该方法。它还提供了一个具体的 describe
方法,该方法使用抽象方法。这说明了抽象类如何混合已实现和未实现的功能。
Circle
和 Square
类继承自 Shape
,并提供了它们对 area
的特定实现。该示例表明我们不能直接实例化 Shape
- 我们必须创建具体子类的实例。
$ dart run basic_abstract.dart This shape has an area of 78.53975 This shape has an area of 16.0
抽象类作为接口
Dart 没有单独的接口关键字 - 抽象类通常用作接口。本示例展示了如何使用抽象类来定义多个类可以不同地实现的契约。
abstract class PaymentProcessor { void processPayment(double amount); void refundPayment(double amount); } class CreditCardProcessor implements PaymentProcessor { @override void processPayment(double amount) { print('Processing credit card payment: \$$amount'); } @override void refundPayment(double amount) { print('Refunding credit card payment: \$$amount'); } } class PayPalProcessor implements PaymentProcessor { @override void processPayment(double amount) { print('Processing PayPal payment: \$$amount'); } @override void refundPayment(double amount) { print('Refunding PayPal payment: \$$amount'); } } void processOrder(PaymentProcessor processor, double amount) { processor.processPayment(amount); } void main() { var creditCard = CreditCardProcessor(); var paypal = PayPalProcessor(); processOrder(creditCard, 100.0); processOrder(paypal, 50.0); }
PaymentProcessor
抽象类定义了一个支付处理器必须实现的接口。与使用 extends
不同,使用 implements
要求子类提供所有方法的实现,包括抽象类的具体方法。
该示例演示了多态性 - processOrder
函数接受任何 PaymentProcessor
实现。这种模式对于创建可插入式架构非常有用,因为实现可以轻松替换。
$ dart run interface_abstract.dart Processing credit card payment: $100.0 Processing PayPal payment: $50.0
带属性的抽象类
抽象类可以定义子类必须实现的抽象属性。本示例显示了一个同时具有抽象属性和具体属性的抽象类。
abstract class Vehicle { // Abstract property String get name; // Concrete property int wheels = 4; // Abstract method void move(); // Concrete method using abstract members void describe() { print('$name with $wheels wheels is moving'); move(); } } class Car extends Vehicle { @override final String name; Car(this.name); @override void move() { print('Vroom vroom!'); } } class Bicycle extends Vehicle { @override final String name = 'Bicycle'; @override int wheels = 2; @override void move() { print('Pedaling...'); } } void main() { var car = Car('Tesla'); var bike = Bicycle(); car.describe(); bike.describe(); }
Vehicle
抽象类声明了一个抽象的 name
属性和 move
方法,同时提供了默认的 wheels
值和具体的 describe
方法。Car
和 Bicycle
类以不同的方式实现这些。
这演示了抽象类如何定义接口的必需和可选方面。wheels
属性展示了具体子类如何覆盖抽象类的默认值。
$ dart run properties_abstract.dart Tesla with 4 wheels is moving Vroom vroom! Bicycle with 2 wheels is moving Pedaling...
带 Mixin 的多重继承
Dart 的 Mixin 可以与抽象类一起使用,以实现类似多重继承的行为。本示例将抽象类与 mixin 结合起来,以创建灵活的类层次结构。
abstract class Animal { String get name; void makeSound(); } mixin Walker { void walk() { print('Walking...'); } } mixin Swimmer { void swim() { print('Swimming...'); } } class Dog extends Animal with Walker { @override final String name; Dog(this.name); @override void makeSound() => print('Woof!'); } class Duck extends Animal with Walker, Swimmer { @override final String name; Duck(this.name); @override void makeSound() => print('Quack!'); } void main() { var dog = Dog('Buddy'); var duck = Duck('Donald'); dog.makeSound(); dog.walk(); duck.makeSound(); duck.walk(); duck.swim(); // Can't instantiate abstract class // var animal = Animal(); }
Animal
抽象类定义了核心的动物行为,而 Walker
和 Swimmer
mixin 则添加了特定的功能。Dog
和 Duck
类以不同的方式组合了这些功能。
这种模式允许灵活的代码重用,同时保持清晰的类层次结构。抽象类确保满足某些契约,而 mixin 提供模块化行为,可以根据需要混合使用。
$ dart run mixin_abstract.dart Woof! Walking... Quack! Walking... Swimming...
抽象类中的工厂构造函数
抽象类可以具有返回具体子类实例的工厂构造函数。这对于创建对象而不暴露具体实现很有用。
abstract class Logger { void log(String message); factory Logger(String type) { switch (type.toLowerCase()) { case 'console': return ConsoleLogger(); case 'file': return FileLogger(); default: throw ArgumentError('Unknown logger type: $type'); } } } class ConsoleLogger implements Logger { @override void log(String message) { print('CONSOLE: $message'); } } class FileLogger implements Logger { @override void log(String message) { print('FILE: $message (written to log file)'); } } void main() { var consoleLogger = Logger('console'); var fileLogger = Logger('file'); consoleLogger.log('This is a console message'); fileLogger.log('This should go to a file'); try { var unknownLogger = Logger('database'); } catch (e) { print('Error: $e'); } }
Logger
抽象类定义了一个工厂构造函数,该构造函数根据输入参数返回不同的日志记录器实现。这会将具体类隐藏起来,使消费者只能与抽象接口进行交互。
这种模式对于创建在运行时需要确定确切实现的对象的很有用。它提供了一种封装对象创建逻辑的干净方法,同时为客户端维护简单的接口。
$ dart run factory_abstract.dart CONSOLE: This is a console message FILE: This should go to a file (written to log file) Error: ArgumentError: Unknown logger type: database
来源
Dart 抽象类
Dart Mixins
Dart 工厂构造函数
抽象类是 Dart 中创建灵活、可维护类层次结构的强大工具。它们能够实现多态、代码重用和清晰的接口定义。通过将抽象类与 mixin 和工厂构造函数结合使用,您可以构建复杂而简洁的面向对象设计。
作者
列出 所有 Dart 教程。