編程那麼多年,C,C++,OC,Swift,JS,Java都有用過。但是最新實驗了下Dart的abstract class mixin幾個關鍵字,把我弄得有點迷糊,似乎他們之間可以互相替代的,究竟他們之間有什麼不同,什麼情況使用什麼呢。
1.定義
關鍵字 | 作用 |
---|---|
abstract | 抽象類,在Java,C++中都是接口抽象類,可以定義屬性和虛函數,等着實現類去實現定義的方法。相當於Swift和OC的protocol,Swift裏可以使用extension實現默認方法,但是在Dart裏抽象類可以直接默認實現方法和屬性,只是不能新建實例類。 |
class | 類,可以新建實例,可以extends,implements,Mixin |
mixin | 通過創建一個繼承自 Object 且沒有構造函數的類,來 實現 一個 Mixin 。 如果 Mixin 不希望作爲常規類被使用,使用關鍵字 mixin 替換 class 。 |
2.abstract class
在Dart中特點:
- 不能實例化
- 接口抽象
- 可以默認實現方式
- 可以被別的類實現和繼承,抽象類可以直接繼承
代碼例子說明:
2.1、abstract class 默認實現方法
需要使用 實現類 extends 之後調用,使用implements需要實現默認方法。
main(List<String> args) {
final wp = Woman();
final m = Man("小明");
wp.run();
m.run();
}
abstract class Person {
run() {
print("奔跑");
}
}
class Man extends Person {
}
class Woman implements Person {
@override
run() {
print("女神跑步");
}
}
打印結果:
女神跑步
奔跑
2.2、抽象類被抽象類繼承
abstract class Person {
Person(this.name);
final String name;
talk();
run() {
print("奔跑");
}
}
abstract class Student extends Person {
Student(String name) : super(name);
int age;
study() {
print("學習");
}
hasClass();
}
class Child implements Student {
@override
int age;
@override
hasClass() {
// TODO: implement hasClass
throw UnimplementedError();
}
@override
// TODO: implement name
String get name => throw UnimplementedError();
@override
run() {
// TODO: implement run
throw UnimplementedError();
}
@override
study() {
// TODO: implement study
throw UnimplementedError();
}
@override
talk() {
// TODO: implement talk
throw UnimplementedError();
}
}
總結:abstract class被abstract class繼承,繼承需要實現父類構造函數。
2.3、abstract class 被Class extends和implements的區別
abstract class Person {
Person(this.name);
final String name;
talk();
run() {
print("奔跑");
}
}
class Man extends Person {
Man(String name) : super(name);
@override
talk() {
print("man talk");
}
}
class Woman implements Person {
@override
String get name => "女神";
@override
run() {
print("女神跑步");
}
@override
talk() {
print("女神說話");
}
}
上面例子,Man 類繼承Person 抽象類,Woman 類實現Person抽象類,可以看出區別如下:
- extends 自動生成abstract 的構造方法,implements則不會
- extends 不需要實現屬性可以直接利用父類, implements需要實現。
- extends 不需要實現默認方法可以直接利用,implements需要實現。(重要)
- 接口定義方法 extends和implements都需要實現。
3. class
Dart的Class特點: 可以當做抽象接口類被實現
代碼例子:
class Person {
final String name;
Person(this.name);
talk() {
print("person talk");
}
run() {
print("person run");
}
}
class Woman implements Person {
@override
// TODO: implement name
String get name => throw UnimplementedError();
@override
run() {
// TODO: implement run
throw UnimplementedError();
}
@override
talk() {
// TODO: implement talk
throw UnimplementedError();
}
}
4. mixin
通過創建一個繼承自 Object 且沒有構造函數的類,來 實現 一個 Mixin 。 如果 Mixin 不希望作爲常規類被使用,使用關鍵字 mixin 替換 class 。
- mixin 沒有構造函數,不能被實例化
- 可以當做接口使用,class 混入之後需要實現
- 默認方法不需要實現(這個是和abstract 的區別)
- 如果一個類with,方法相同,先執行本體方法,然後按照混入順序,執行最後mixin方法。
- 可以使用on 指定混入的類類型,如果不是報錯。
代碼演示:
main(List<String> args) {
final man = Man("男神");
man.classes();
man.study();
}
class Person {
final String name;
Person(this.name);
talk() {
print("person talk");
}
run() {
print("person run");
}
}
class Man extends Person with Student {
Man(String name) : super(name);
@override
study() {
print("man study");
}
classes() {
print("三年8班");
}
}
mixin Student {
int age;
study();
classes() {
print("三年二班");
}
run() {
print("student run");
}
}
打印結果:
三年8班
man study
5. 總結
根據以上特性總結下,在工作中什麼情況,使用哪種關係結構。
主關係 | 方式 | 子關係 | 用途 |
---|---|---|---|
class | extends | abstrct | 當需要共通的構建方法和默認屬性、方法的時候,同時需要重新實現接口方法。 |
abstrct | extends | abstrct | 子抽象,類似class 繼承關係。 |
class | implements | abstrct | 每一個子關係都需要抽象定義所有的接口規範 ,規範類不需要實例 |
class | implements | class | 每一個子關係都需要抽象定義所有的接口規範 ,規範類需要實例化 |
class | with | mixin | 主關係混入子關係的內容,子關係不需要實例化 |
class | with | class | 主關係混入子關係的內容,子關係需要實例化 |
class | with on | mixin | 主關係混入子關係的內容,主關係必須是一個特點的類型,子關係不需要實例化 |