--- 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! } ```