Dart 語法學習目錄
第一節: Dart 語法了解,認識變量,常量,數據類型
第二節: Dart 操作符(運算符)
第三節: Dart 中流程控制,條件判斷以及循環語句
第四節: Dart 中常用集合 List/Map
第五節: Dart 函數使用,聲明函數/匿名函數/可選參數/作用域/閉包
第六節: Dart 面向對象/構造函數/靜態屬性
第七節: Dart中抽象類abstract/接口implements/混入Mixin
第八節: Dart中泛型/泛型定義與使用
第九節: Dart 中的庫/自定義庫/內置庫/第三方庫
1. Dart 泛型
1.1 泛型的理解
在 API 文檔中你會發現基礎數組類型 List 的實際類型是
List<E>
。 <…> 符號將 List 標記為 泛型 (或 參數化) 類型。 這種類型具有形式化的參數。 通常情況下,使用一個字母來代表類型參數, 例如 E, T, S, K, 和 V 等。
泛型:通俗的理解: 就是解決類的接口, 方法, 復用性, 以及對不特定數據類型的支持(類型校驗),
在通俗一點,就是對于類型的約束.
1.2 泛型的定義
- 使用
<…>
來聲明泛型 - 通常情況下,使用一個字母來代表類型參數, 例如
E
,T
,S
,K
, 和V
等。 -
List
定義的泛型*(或者 參數化) 類型,定義為List<E>
。
1.3 使用泛型的原因
- 在 Dart 中類型是可選的,可以通過泛型來限定類型。
- 使用泛型可以有效地減少重復的代碼。
- 泛型可以在多種類型之間定義同一個實現,同時還可以繼續使用檢查模式和靜態分析工具提供的代碼分析功能。
- 如果你需要更加安全的類型檢查,則可以使用 參數化定義。
1.4 泛型的好處
泛型的好處不僅僅是保證代碼的正常運行:
- 正確指定泛型類型可以提高代碼質量。
- 使用泛型可以減少重復的代碼。
接下來看看泛型的使用
2. 泛型的使用
在使用泛型之前,我們先看看一些需求,來理解泛型
需求: 有一個類, 輸入什么類型返回什么類型
2.1 需求示例理解泛型的使用場景
那么我們可能會如下的寫法
void main(){
int getInfo(int value){
return value;
}
var num = getInfo(123);
print(num);
}
這樣的寫法只能滿足我們在傳入數字類型,返回數字類型,如果傳入字符串類型就會報錯,
這樣的局限性就會很大,如果你還想開發一個傳入字符串類型,返回字符串類型的函數,你就需要在一個函數.這樣代碼量就會變的很大,那么怎樣才能讓一個方法復用呢,減少代碼量
那么有些人可能就會在想,我們可以把類型限制去掉
如下
void main(){
getInfo(value){
return value;
}
var num = getInfo(123);
print(num);
}
這樣雖然可以實現最開始的學需求,但是這么寫毫無意義. 在真實開發中,隨時有可能你傳入的值和返回的值類型不同
void main(){
getInfo(value){
value = '' + value;
return value;
}
var num = getInfo(123);
print(num);
}
如示例,這樣不會報錯,同時也不會有類型檢查
所以我們就可以使用泛型,泛型簡而言之,就是我不知道用戶輸入什么類型的值, 用一個標記符號代替,這個標記符號就是這種類型,在所有需要同一類型的地方使用這種標記,
那么這個標記到底代表什么類型,等到被調用的時候由用戶來制定.
例如:
void main(){
T getInfo<T>(T value){
return value;
}
// 制定getInfo 參數和返回都是int類型
var num = getInfo<int>(123);
print(num); // 123
print(num is int); // true
// 指定getInfo 參數和返回都是String類型
var str = getInfo<String>("hello");
print(str); // hello
print(str is String); // true
}
通過例子我們就會了解,函數的參數的類型和返回的類型不是有定義函數是決定的,而是用了一個字母T代表類型,這個類型在調用這個方法的時候才會決定.
當然了,可能會有人問,那么我在調用的時候可不可以不指定類型, 完全沒有問題,
如下調用依然可以
var num = getInfo(123);
print(num); // 123
print(num is int); // true
此時你就可以傳入任何類型
其實dart有很多內置的方法都是用了泛型,我們可以通過下面了解
2.2 了解dart內置方法的泛型
dart中很多類都定義了泛型,就以List
為例來看看dart中內置的泛型
void main(){
// 未指定類型的List
List list = List();
list.add("蘋果");
list.add(123);
print(list); // [蘋果, 123]
// 限定List 泛型為String
List list2 = List<String>();
list2.add("李子");
list2.add(333);
print(list2); //報錯: type 'int' is not a subtype of type 'String' of 'value'
}
這個時候機會發現, List
中的類型不是在定義時決定的,而是在使用時決定的,如果在使用List
時沒有指定類型,那么list
中可以添加任何類型的內容, 如果指定了特定的類型,這個集合中將只能傳入指定類型的數據,否則就報錯,類型不對.
那么接下來就看看泛型的使用
2.3 泛型函數
最初,Dart 的泛型只能用于類。 新語法的泛型,允許在方法和函數上使用類型參數:
其實上面的示例中我們已經用到了泛型函數,
示例:
T getInfo<T> (T value){
T num = value;
return num;
}
示例函數中不同的T
各表示什么意思
T
(表示getInfo返回值的類型) getInfo<T>
這個T就是接受使用getInfo時指定的類型 (T
(參數類型) value) {?
T
定義變量時的類型
num =value;}
所有T表示的類型都是一樣的, 由使用函數的時候指定的類型.
函數使用泛型地方說明
- 函數的返回值類型 (T)。
- 參數的類型 (T value).
- 局部變量的類型 (T num).
至于函數名后面的<T>
,負責接受來確定T
代表哪一種類型.
2.4 類泛型
dart中可以在定義類是使用泛型.
在類名字后面使用尖括號(<...>
)來指定 泛型類型。
class Person<T>{
T sayhello(T value){
print("hello,我是$value");
return value;
}
}
void main(){
Person student = new Person<String>();
var name = student.sayhello("小明"); // hello,我是小明
print(name); // 小明
print(name is String); // true
}
在定義類時使用泛型, 類中的方法,包括屬性都可以使用泛型
3. 限制泛型類型
說明:
當需要對泛型的具體類型進行限定的時候,可以使用extends
關鍵字來限定泛型參數的具體類型。
3.1 不限制泛型類型的時候
也就是說我們制定定義的泛型是完全由使用這決定的
例如
class Person<T>{
T sayhello(T value){
print("hello,我是$value");
return value;
}
}
void main(){
Person student = new Person<String>();
var name = student.sayhello("小明"); // hello,我是小明
print(name); // 小明
print(name is String); // true
Person student2 = new Person<int>();
var name2 = student2.sayhello(123); // hello,我是123
print(name2); // 123
print(name2 is int); // true
}
類Person
中T所代表的類型完全是使用時指定什么類型就是什么類型,
但是有的時候就需要對泛型進行限制.
3.2 限制泛型的類型
在需要的使用通過extends
類限定泛型的類型
將上例中的泛型加以限制.
示例:
class Person<T extends String>{
T sayhello(T value){
print("hello,我是$value");
return value;
}
}
一旦你更改后在此運行,你會發現報錯, 因為此時使用這個類型,泛型只能是字符串類型, 你傳入的數字類型就會報錯