---
# System prepended metadata

title: Dart extends、 implements、with的用法與區別
tags: [Flutter, Dart]

---

---
title: 'Dart extends、 implements、with的用法與區別'
tags: Dart
disqus: hackmd
---

<style>
.red {
  color: red;
}
    .blue {
        color: blue;
    }
</style>

<font size="6">Dart extends、 implements、with的用法與區別</font>

**目錄：**

[TOC]

## 概述

- 繼承（關鍵字extends)
- 混入mixins (關鍵字with)
- 接口實現（關鍵字implements）

這三種關係有可能同時存在，但是撰寫上有先後順序
優先級：
extends -> with -> implements

但實際執行上
優先級：
with比extends高

## Dart中類的類型

- class：聲明一個類，提供具體的成員變量和方法實現。
- abstract class：聲明一個抽像類，抽像類將無法被實例化。抽像類常用於聲明接口方法、有時也會有具體的方法實現。
- mixin：聲明一個Mixin類，與抽像類一樣無法被實例化，是一種在多重繼承中復用某個類中代碼的方法模式，可以聲明接口方法或有具體的方法實現。

而對上述這些類型的使用，又有extends, with, implements,on這幾個關鍵字：

- extends：繼承，和其它語言的繼承沒什麼區別。
- with：使用Mixin模式混入一個或者多個Mixin類。
- implements：實現一個或多個接口並實現每個接口定義的API。
- on：限制Mixin的使用範圍。

## 範例

### 類混入類或者抽像類（class with class）

```dart=
class Animal {
  String name = "Animal";
}
abstract class Flyer {
  String name = "Flyer";
  void fly() => print('$name can fly!');
}
abstract class Eater extends Animal {
  void eat() => print('I can Eat!');
}

// 同時混入class和abstract class
abstract class Bird with Animal, Flyer {}
class Bird1 with Animal, Flyer {}

// 只支持無任何繼承和混入的類，Eater繼承自Animal，所以它不支持被混入。
// 報錯：The class 'Eater' can't be used as a mixin because it extends a class other than 'Object'.
// class Bird with Eater { 
// }

main() {
  Bird1().fly();  // Flyer can fly!
}
```

### 類繼承抽像類並混入Mixin

```dart=
class Animal {
  String name = "Animal";
}

mixin Flyer {
  String name = "Flyer";
  void fly() => print('$name can fly!');
}

abstract class Eater extends Animal {
  @override
  String get name => "Eater";
  void eat() => print('$name can Eat!');
}

// 類繼承抽象類並混入Mixin
class Bird extends Eater with Flyer {  }

main() {
  // 因為with（混入）的優先級比extends（繼承）更高，所以打印出来的name是Flyer而不是Eater
  Bird().fly(); // Flyer can fly!
  Bird().eat(); // Flyer can Eat!
}
```

### 類繼承抽像類並混入Mixin的同時實現接口

```dart=
class Biology {
  void breathe() => print('I can breathe');
}

class Animal {
  String name = "Animal";
}

// 這裡設置實現了Biology接口，但是mixin與abstract class一樣並不要求實現接口，聲明與實現均可。
// on關鍵字限制混入Flyer的類必須繼承自Animal或它的子類
mixin Flyer on Animal implements Biology {
  @override
  String get name => "Flyer";
  void fly() => print('$name can fly!');
}

abstract class Eater extends Animal {
  @override
  String get name => "Eater";
  void eat() => print('$name can Eat!');
}

// 類繼承抽象類並混入Mixin的同時實現接口
// 注意關鍵字的使用順序，依次是extends -> with -> implements
class Bird extends Eater with Flyer implements Biology {
  // 後面使用了`implements Biology`，所以子類必須要實現這個類的接口
  @override
  void breathe() => print('Bird can breathe!');
}

main() {
  // 因為with（混入）的優先級比extends（繼承）更高，所以打印出来的name是Flyer而不是Eater
  Bird().fly(); // Flyer can fly!
  Bird().eat(); // Flyer can Eat!
  Bird().breathe(); // Bird can breathe!
}
```