類型 | 解決什么問題 | 使用場景 | 限制 |
---|---|---|---|
extends | 子類繼承 | 子類繼承父類 | 可以有構(gòu)造方法和實例變量 |
Mixin(with) | 實現(xiàn)類似多繼承糠赦,能力集 | 不通過繼承会傲,獲取一個類的能力 | 不能有構(gòu)造方法,可以有實例變量 |
Extension(on) | 給系統(tǒng)類【例如String類添加功能】 | 在無法修改被擴展類源碼的情況下 | 不能有構(gòu)造方法和實例變量 |
Implement | 聲明和實現(xiàn)的解耦 | 模版方法的實現(xiàn)【設(shè)計模式的一種】 | 暫無 |
繼承(extends)
使用extends關(guān)鍵詞來繼承父類
- 子類會繼承父類里面可見的屬性和方法 但是不會繼承構(gòu)造函數(shù)
- 子類能復(fù)寫父類的方法 getter和setter
- 子類重寫超類的方法拙泽,要用@override
- 子類調(diào)用超類的方法唆铐,要用super
- 子類可以繼承父類的非私有變量 (類中私有變量和函數(shù)的定義:名稱前面帶_)
class Person {
String? name;
int? age;
/// 構(gòu)造函數(shù)
Person(this.name);
/// 私有屬性,對于子類不可見
String? _birthDay;
/// 計算屬性
bool get isAdult => (age ?? 0) >= 18;
void run() {
print('Person runing');
}
}
class Student extends Person {
/// 子類構(gòu)造函數(shù)
Student(String? name) : super(name);
/// 重寫父類屬性
@override
bool get isAdult => (age ?? 0) > 20;
@override
void run() {
// super.run();
print('Student runing');
}
/// 子類自有方法
void study() {
print("Student can studying");
}
}
void main() {
Student student = Student("li sha");
/// 調(diào)用自己方法
student.study(); // Student can studying
/// 訪問父類屬性
student.age = 18;
/// 調(diào)用父類方法
student.run(); // Person runing
print(student.isAdult); // false
/// 繼承中 多態(tài)的使用
Person person = Student('jekson ');
person.run(); //Student runing
// Tips: Error 這里無法訪問到子類方法奔滑,因為使用多態(tài)生成的對象是Person,Person中沒有study方法
// person.study(); //Student runing
/// 使用is 意思是:將person 轉(zhuǎn)化成 Student對像,就可以訪問子類方法了
if (person is Student) {
person.study();
}
}
tips: 注意繼承中 多態(tài)的使用
混合 mixins (with)
mixins的中文意思是混入(兩個類混合在一起)顺少,就是在類中混入其他功能朋其。簡單的理解,就是在現(xiàn)有類的基礎(chǔ)上脆炎,引入一些新的變量和方法梅猿。
- 作為mixins的類只能繼承自O(shè)bject,不能繼承其他類
- 作為mixins的類不能有構(gòu)造函數(shù)
- 一個類可以mixins多個mixins類
- mixins不是繼承秒裕,也不是接口袱蚓,而是一種全新的特性。
最簡單的mixin
mixin本身可以是抽象的几蜻,可以定義各種方法屬性喇潘,也可以是抽象的,等后續(xù)類去實現(xiàn)
void main(List<String> args) {
XuModel model = XuModel();
model.xuTest2();
model.xutest1();
print('xuValue: ${model.xuValue}');
}
/// mixin本身可以是抽象的梭稚,可以定義各種方法屬性颖低,也可以是抽象的,等后續(xù)類去實現(xiàn)
mixin TestXuMixin {
// 定義屬性
var xuValue = 3;
// 抽象方法
void xutest1();
void xuTest2() {
print('xuTest2');
}
}
class XuModel with TestXuMixin {
@override
void xutest1() {
// 該函數(shù)mixin 定義未實現(xiàn)弧烤,混入對象忱屑,必須要實現(xiàn)
print("xutest1 - xuValue : $xuValue");
}
}
基于某個類型的mixin
當(dāng)使用on關(guān)鍵字(限定類型),則表示該mixin只能在那個類的子類使用了暇昂,那么結(jié)果顯然的莺戒,mixin中可以調(diào)用那個類定義的方法、屬性
class BaseObject {
void method() {
print('call method');
}
}
mixin TestMixin on BaseObject {
void test() {
print('test');
}
int testInt = 1;
void test2() {
method();
}
void test3(); // 抽象方法
}
class Test extends BaseObject with TestMixin {
@override
void test3() {
// TODO: implement test3
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 1
Test().test2(); // call method
}
多個mixin
如果mixin存在沖突的部分急波,后面會覆蓋前面的从铲,沒有沖突的則會保留,所以可以存在后面的mixin修改了前面的mixin的一部分邏輯的情況澄暮,不需要直接繼承即可實現(xiàn)覆蓋食店,避免了更復(fù)雜的繼承關(guān)系
mixin TestMixin {
void test() {
print('test');
}
int testInt = 1;
void test2();
}
mixin TestMixin2 {
int testInt = 2;
void test3() {
print('test3');
}
}
class Test with TestMixin, TestMixin2 {
@override
test2() {
print('test2');
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 2 后面會覆蓋前面的mixin
Test().test2(); // test2
Test().test3(); // test3
}
mixin實現(xiàn)多重繼承
mixin TestMixin on BaseClass {
void init() {
print('TestMixin init start');
super.init();
print('TestMixin init end');
}
}
mixin TestMixin2 on BaseClass {
void init() {
print('TestMixin2 init start');
super.init();
print('TestMixin2 init end');
}
}
class BaseClass {
void init() {
print('Base init');
}
BaseClass() {
init();
}
}
class TestClass extends BaseClass with TestMixin, TestMixin2 {
@override
void init() {
print('TestClass init start');
super.init();
print('TestClass init end');
}
}
void main() {
TestClass();
/// TestClass init start
/// TestMixin2 init start
/// TestMixin init start
/// Base init
/// TestMixin init end
/// TestMixin2 init end
/// TestClass init end
}
接口實現(xiàn)(implements)
接口的實現(xiàn)渣淤,基于定義的一個抽象類,抽象類中僅定義方法吉嫩,沒有具體的實現(xiàn)价认,子類通過implements的方法,在子類中實現(xiàn)具體的方法自娩。
- implements與extends最?的不同就是允許后?接上多個普通或者抽象類用踩,當(dāng)我們使?B implement A修飾時,那么A中的所有的屬性和?法都要在B中實現(xiàn)忙迁,?論它原來是抽象?法還是普通?法脐彩。
abstract class Run {
var runValue;
void runing() {
print('runding');
}
}
abstract class Eat {
void eat();
}
class Person implements Run, Eat {
@override
void runing() {
print("Person runing");
}
@override
void eat() {
print("Person eating");
}
@override
var runValue = 100;
}
class Lion extends Run with Eat {
/// 抽象類中實現(xiàn)的方法
/// 繼承抽象類可以不用實現(xiàn)(子類繼承父類方法,可以選擇是否重寫)
@override
void runing() {
/// 繼承抽象類可以調(diào)用super
super.runing();
print("Lion runing");
}
@override
void eat() {
print("Lion eating");
}
}
void main(List<String> args) {
Person().runing();
Person().eat();
Lion().eat();
Lion().runing();
}
tips:
mixin:定義了組塊姊扔。
mixin on:限定了使?組塊的宿主必須要繼承于某個特定的類惠奸;在mixin中可以訪問到該特定類的成員和?法。
with負(fù)責(zé)組合組塊恰梢,而with后?跟的類并不?定需要是mixin的佛南,abstract class 和普通類都可以。
extends with 修飾會覆蓋同名方法嵌言,with中后一個覆蓋前一個