【Flutter 基礎(chǔ)】 泛型

當(dāng)我們查看 Flutter 源碼的時(shí)候會發(fā)現(xiàn)源碼中有大量的 、 代碼,比如 List 的源代碼
abstract?class?List<E>?implements?EfficientLengthIterable<E>?{
<..> 標(biāo)記表示泛型的概念,通常情況下,泛型使用單字母表示,比如:E,T,S,K和V。
為什么要使用泛型?它有什么作用?
在編譯階段進(jìn)行類型安全檢查
一個(gè)重要的作用是泛型會在編譯階段進(jìn)行類型安全檢查,比如有一個(gè) String 類型集合:
List<String>?list?=?[];
list 是一個(gè)String類型的集合,list 中的元素必須是String類型,添加其他類型時(shí)編譯階段報(bào)錯(cuò)
list.add(1);?//編譯不通過
假設(shè)不使用泛型,定一個(gè)集合:
List?list1?=?[];
list1 中可以添加任意類型的數(shù)據(jù):
list1.add('value');
list1.add(1);
編譯都可以通過,list1 等價(jià)于如下的定義:
List<dynamic>?list1?=?[];
減少重復(fù)代碼
泛型可以有效的減少重復(fù)代碼,一個(gè)典型使用場景:服務(wù)端返回的接口通常是統(tǒng)一的格式,比如返回如下json格式:
{
?"code":?0,
?"msg":?"",
?"data":?{}
}
每一個(gè)接口都會返回 code 和 msg,data 為業(yè)務(wù)數(shù)據(jù),可以每一個(gè)接口返回的實(shí)體類型都進(jìn)行如下定義:
class?Data1{
??String?code;
??String?msg;
??dynamic?data;
}
這是每一個(gè)實(shí)體類型都會包含code 和 msg字段,我們可以使用泛型去掉重復(fù)代碼:
class?DataBase<T>{
??String?code;
??String?msg;
??T?data;
}
class?Person?{
??String?name;
??Person(this.name);
}
使用:
var?data?=?DataBase<Person>();
List Map Future Stream 使用泛型
在實(shí)際開發(fā)中,泛型幾乎無處不在,下面介紹幾個(gè)常用的場景。
List指定集合元素類型:
List<int>?list?=?[];
list.add(1);
list集合指定的類型為 int,只能添加 int 類型數(shù)據(jù)。
Map<K, V> 指定key、value的類型:
Map<String,int>?map?=?{'key':1,'key1':2};
map 指定key的類型為 String,value的類型為 int。
Future 和 Stream 使用泛型,是異步泛型,返回指定類型。Future 和 Stream 完成的時(shí)候要么返回指定的類型值要么返回異常。
比如 Future 返回一個(gè) String 類型:
Future<String>?fun3()?{
??return?Future.value('flutter');
}
Stream 使用泛型:
var?streamController?=?StreamController<String>.broadcast();
Stream<String>?get?data?=>?streamController.stream;
限制泛型
限制泛型并不是不使用泛型,而是對泛型的類型進(jìn)行限制,使用 extends 關(guān)鍵字:
定義一個(gè)基類:
class?DataBase{}
定義 Data 類,此類的泛型需要是DataBase或者其子類:
class?Data?<T?extends?DataBase>{}
這里指定了 T 集成 DataBase。
定義DataBase子類Person:
class?Person?extends?DataBase{
??String?name;
??Person(this.name);
}
那么如下用法是正確的:
var?data?=?Data<Person>();
var?data1?=?Data<DataBase>();
但是下面的用法是錯(cuò)誤的:
var?data2?=?Data<String>();?//error
class?Person1{}
var?data3?=?Data<Person1>();//error
方法中使用泛型
定義如下方法:獲取集合中第2個(gè)元素值,集合中元素值為任意類型:
class?Data<T>?{
??T?getSecond(List<T>?list)?{
????return?list[1];
??}
}
在類中使用泛型
class?DataBase<T>?{
??T?_data;
??T?getData(){
????return?_data;
??}
}
泛型是非常重要的概念,尤其是寫插件和框架的時(shí)候。當(dāng)查看Flutter源碼和第三方插件的源碼時(shí)泛型隨處可見。
你可能還喜歡關(guān)注「老孟Flutter」讓你每天進(jìn)步一點(diǎn)點(diǎn)
