Dart之消息、继承、多态

Dart之消息、继承、多态

Dart之消息、继承、多态思维导图

一、前言

上一篇面向对象基础里,我们已经知道:类像设计图,对象是具体实例。

但对象不是孤零零存在的。真正的程序里,对象之间要协作:一个对象请求另一个对象做事,子类复用父类能力,不同对象对同一个行为做出不同反应。

这就引出了三个重要概念:消息、继承、多态。

可以先用一句生活化的话理解:

  • 消息是对象之间沟通的桥梁。
  • 继承是已有能力的传递。
  • 多态是同一个动作在不同对象上呈现不同效果。

二、一句话理解

消息让对象之间发生协作,继承让子类复用父类能力,多态让同一个调用在不同对象上产生不同表现。

简单说:

  • 消息:对象调用另一个对象的方法。
  • 继承:子类获得父类的非私有属性和方法。
  • 多态:父类类型接收子类对象,调用时表现出子类行为。

三、消息

3.1 消息是什么

消息是对象之间通信的一种方式。

在代码里,一个对象调用另一个对象的方法,本质上就可以理解为发送消息。

消息通常包含四个部分:

组成 含义
发送者 发起请求的对象
接收者 接收请求的对象
操作 要执行的方法
参数 执行方法需要的数据

例如:

receiver.receiveMessage('Hello, Dart!');

这里可以理解为:给 receiver 发送一条消息,请它执行 receiveMessage,参数是 'Hello, Dart!'

3.2 消息传递

消息传递是对象协作的过程。

class Receiver {
  void receiveMessage(String message) {
    print(message);
  }
}

class Sender {
  void sendMessage(Receiver receiver, String message) {
    receiver.receiveMessage(message);
  }
}

void main() {
  Receiver receiver = Receiver();
  Sender sender = Sender();

  sender.sendMessage(receiver, 'Hello, Dart!');
}

这个例子中:

  • sender 是发送者。
  • receiver 是接收者。
  • receiveMessage 是接收者要执行的操作。
  • 'Hello, Dart!' 是消息参数。

对象之间不是直接访问彼此内部细节,而是通过方法进行协作。

3.3 消息传递的优势

消息传递的价值不只是“能调用方法”,它背后有几个重要优势:

  • 解耦:发送者不需要知道接收者内部怎么实现。
  • 灵活:可以根据不同对象调用不同方法。
  • 可扩展:新增能力时,可以扩展对象方法。
  • 复用:相同协作方式可以复用。
  • 支持多态:同一个消息可以在不同对象上表现不同。

消息传递让对象之间有边界。边界清楚,代码就更容易维护。

四、继承

4.1 继承是什么

继承是子类和父类之间共享属性和方法的机制。

可以把它理解成能力传递:父类提供通用能力,子类在此基础上扩展或改写。

class Animal {
  String name;

  Animal(this.name);

  void roar() {
    print('The $name is roaring');
  }
}

class Dog extends Animal {
  Dog(super.name);
}

void main() {
  Dog dog = Dog('dog');
  dog.roar();
}

Dog 继承了 Animal,所以拥有 nameroar()

4.2 继承的优势

继承的优势主要有:

  • 代码复用:公共属性和方法放在父类中。
  • 扩展能力:子类可以新增自己的属性和方法。
  • 结构清晰:类之间形成层次关系。
  • 支持多态:父类引用可以指向子类对象。

例如:

class Dog extends Animal {
  Dog(super.name);

  void run() {
    print('$name is running');
  }
}

Dog 既有 Animal 的能力,又有自己的 run()

4.3 方法重写

子类可以重写父类方法,定制自己的行为。

class Dog extends Animal {
  Dog(super.name);

  @override
  void roar() {
    print('$name is running!');
  }
}

void main() {
  Animal animal = Animal('animal');
  Dog dog = Dog('dog');

  animal.roar();
  dog.roar();
}

@override 表示这个方法重写了父类方法。它能让代码意图更清楚,也能帮助工具检查错误。

4.4 继承相关概念

几个术语要分清:

概念 含义
基类 / 父类 被继承的类
派生类 / 子类 继承而来的类
继承层次 多个类形成的树状结构
重写 子类重新定义父类已有方法
super 在子类中访问父类成员

super 常用于调用父类构造函数或父类方法。

class Dog extends Animal {
  Dog(super.name);

  @override
  void roar() {
    super.roar();
    print('$name says wang wang');
  }
}

4.5 继承的边界

继承不是越多越好。

继承适合表达 “is-a” 关系:

  • Dog is an Animal.
  • Cat is an Animal.

如果只是一个对象“拥有”另一个对象,更适合组合。

例如汽车拥有发动机,不应该说汽车是发动机。

五、多态

5.1 多态是什么

多态就是同一个接口或同一个方法调用,在不同对象上表现出不同结果。

可以想象一个打印按钮:传入黑白打印机,打印黑白;传入彩色打印机,打印彩色。按钮动作一样,但对象不同,效果不同。

5.2 运行时多态

Dart 中最常见的是运行时多态,也就是子类重写父类方法。

class Animal {
  String name;

  Animal(this.name);

  void roar() {
    print('$name makes sound');
  }
}

class Dog extends Animal {
  Dog(super.name);

  @override
  void roar() {
    print('$name 汪汪');
  }
}

class Cat extends Animal {
  Cat(super.name);

  @override
  void roar() {
    print('$name 喵喵');
  }
}

void main() {
  List<Animal> animals = [
    Dog('小狗'),
    Cat('小猫'),
  ];

  for (final animal in animals) {
    animal.roar();
  }
}

变量列表的类型是 List<Animal>,但里面放的是 DogCat。调用同一个 roar(),输出不同结果。

这就是多态的价值。

5.3 编译时多态要注意

原文中提到编译时多态,也就是方法重载。

但 Dart 和 Java 这类语言不同,Dart 不支持在同一个类中通过不同参数列表定义多个同名方法。

例如下面这种写法在 Dart 中不成立:

class Calculator {
  // Dart 不支持这样写多个同名 add 方法
  // int add(int a, int b) => a + b;
  // double add(double a, double b) => a + b;
}

Dart 更常用的方式是使用可选参数、命名参数、泛型或不同方法名来表达不同调用形式。

class Calculator {
  num add(num a, num b) {
    return a + b;
  }
}

这一点需要特别注意,不能把其他语言里的重载机制直接套到 Dart 上。

5.4 多态的好处

多态的好处是让调用方依赖抽象,而不是依赖具体类。

void makeAnimalSound(Animal animal) {
  animal.roar();
}

void main() {
  makeAnimalSound(Dog('小狗'));
  makeAnimalSound(Cat('小猫'));
}

makeAnimalSound 不关心传进来的是狗还是猫,只关心它是 Animal,能执行 roar()

这样代码会更灵活,也更容易扩展。

六、消息、继承、多态之间的关系

这三个概念不是孤立的。

  • 消息让对象之间能协作。
  • 继承让类之间能复用和扩展。
  • 多态让同一个消息在不同子类对象上表现不同。

例如:

void makeAnimalSound(Animal animal) {
  animal.roar();
}

这行代码里:

  • animal.roar() 是消息传递。
  • DogCat 继承自 Animal
  • 运行时根据真实对象调用不同 roar(),这是多态。

把它们放在一起理解,会比单独背概念更清楚。

七、常见误区

7.1 以为继承只是复制代码

继承不是简单复制父类代码,而是表达类之间的层次关系。

如果没有 “is-a” 关系,优先考虑组合。

7.2 忽略 Dart 不支持传统方法重载

Dart 不支持同类中多个同名不同参数的方法重载。需要用可选参数、命名参数、泛型或不同方法名解决。

7.3 以为多态必须写很多 if

多态的价值恰恰是减少大量类型判断。

for (final animal in animals) {
  animal.roar();
}

调用方不需要判断 animal 是狗还是猫,对象自己知道怎么表现。

7.4 子类重写方法忘记 @override

@override 不是强制必须,但建议写。

它能表达意图,也能帮助工具发现方法名写错、签名不一致等问题。

八、总结

这一篇我们系统讲了 Dart 中的消息、继承和多态。

消息是对象之间的沟通方式,本质上就是对象之间通过方法调用协作。

继承让子类复用父类的非私有属性和方法,也能在父类基础上扩展和重写。

多态让同一个方法调用在不同对象上有不同表现,是面向对象灵活性的关键。

最后记住一句话:

对象通过消息协作,类通过继承复用,行为通过多态扩展。

posted @ 2026-08-10 21:57  好的佩奇  阅读(8)  评论(0)    收藏  举报