Dart之旅
一。重要概念
1.所有的變量都是個對象,而所有的對象都是類的實例,甚至數字,函數以及null都是對象,包括null異常在哪,所有對象都繼承自Object。
2.Null safety(空安全)是從2.12版本的dart引入的
3.盡管dart是強類型的,但是類型注解也是可用的因為dart可以推斷類型
4.如果啟用null safety,變量不能包含null,除非你告訴他們可以為空。你可以在變量類型的后面跟上一個?來是一個變量變?yōu)榭煽盏摹?br> 比如說,一個變量的類型是int?那么它可能是一個integer也坑是個null,如果你知道一個表達式不可能值為null,但是Dart語言不允許,你可以在他后面加一個!來生命他不會為空(如果它真的為空了,就會拋出一個異常)
5.當你想顯式的聲明變量,那么什么類型都可以用,比如Object?(如果啟用了null safety),Object或者-如果你一定要推遲類型檢查直到runtime才推斷(也就是特殊的類型dynamic)
6.Dart支持范型,比如List<int>或者List<Object>
7.Dart支持頂級函數(比如main()),也支持類上或者是對象上的函數(也就是靜態(tài)函數和成員函數),你同樣也可以在函數內創(chuàng)建函數(也就是嵌套函數或者是本地函數)
8.相似的,Dart支持頂級變量同樣支持靜態(tài)變量和成員變量。成員變量有時候也被稱為字段or屬性。
9.不像Java,Dart沒有public,protected,和private 關鍵字,如果一個變量or函數or類是開頭的,那么他就是private。
10.標識符(類,函數,方法等)可以用小寫字母開頭或者下劃線開頭(),然后任意組合小寫字母,下劃線數字等
11.Dart有表達式(有運行時的值)和聲明(沒有運行是的值),比如,條件表達式?:expr1:expr2有一個值要么是expr1,要么是expr2。與之相比的就是if-else語句,它并沒有值。一個語句通常包括一個或者多個表達式,但是一個表達式卻不能直接包含一個語句。
12.Dart工具能報告兩種類型的問題:warning和error,Warning只是提示代碼可能會出錯但是并不阻止程序的執(zhí)行,Error既可以在編譯時也可以在運行時出現,編譯時的error阻止帶啊嗎的繼續(xù)執(zhí)行,而 一個代碼運行時的error則會導致一個異常的拋出。
關鍵字:
1.abstract:抽象類or抽象方法
2.else
3.import:導包
4.show/hide:Importing only part of a library
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
5.as:類型轉換,類似于Android studio 中的cast
(employee as Person).firstName = 'Bob';
6.enum:枚舉
enum Color { red, green, blue }
使用:Color.blue
7.in:主要用于循環(huán)
for (final candidate in candidates) {
candidate.interview();
}
8.static:靜態(tài)類,方法,對象,字段
9.assert:斷言
在開發(fā)中用一個斷言語句-assert(condition,optionalMessage);來中斷一個常規(guī)的執(zhí)行如果一個 條件語句的結果是false。比如:
// Make sure the variable has a non-null value.
assert(text != null);
// Make sure the value is less than 100.
assert(number < 100);
// Make sure this is an https URL.
assert(urlString.startsWith('https'));
10.export:類似于build.gradle里面的exclude
11.interface:接口
12.super:父類
13.async:異步
Dart庫里面充滿了返回Future或者Stream對象的函數,這些函數就是異步的。這些函數經過一段時間的耗時操作,不用等到這些操作完成(沒懂!!!)
async/await是支持異步編程的關鍵字,讓你把異步代碼寫的像同步代碼一樣。
Future<void> checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
14.extends:繼承
15.is:判斷類型使用,類似于Java中的instanceOf
if (employee is Person) {
// Type check
employee.firstName = 'Bob';
}
16.switch:分支,和Java中一樣
17.await:異步編程。和async配合使用
await lookUpVersion();//使異步代碼同步執(zhí)行
想要使用await,代碼必須在一個async方法中也就是方法要被async標記
Future<void> checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
18.extension:擴展(如擴展函數)類似于Kotlin
擴展方法是向已有庫中增加實用性的一種方式,你可能在不經意間就在用擴展方法,比如說,當你在IDE里面做代碼補全的時候,他就會在常規(guī)方法旁邊建議一些擴展方法。
19.late:2.12版本增加的關鍵字
1.生命一個非空變量,可以先聲明后初始化
2.懶初始化一個變量
Dart的流分析一般都會在非空變量使用前檢測到被賦值了一個非空的值但有的時候還是會分析失敗。
如果你確定一個變量在使用前已經被賦值,但是,dart 不允許,你可以把這個變量設置為late來修復這個問題:
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
20.sync:
21.break:跳出循環(huán)或者跳出分支,和Java一樣
22.external:
23.library:就是庫文件
24.this:構造函數中使用
class Point {
double x = 0;
double y = 0;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
25.case:和switch配合使用
26.factory:Factory constructors
實現一個構造器但是并不是每次都創(chuàng)建這個類的實例時,就可以使用factory關鍵字。比如說,factory constructor可能會在緩存里面返回一個實例,也可能返回一個子類型的實例。在初始化列表中使用邏輯不能初始化一個final變量時也可以使用factory constructor。
下面的例子中Logger factory constructor從緩存中返回了對象,Logger.fromJson factory constructor從一個Json Object中初始化了一個final變量。
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
return _cache.putIfAbsent(
name, () => Logger._internal(name));
}
factory Logger.fromJson(Map<String, Object> json) {
return Logger(json['name'].toString());
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
27.mixin:Adding features to a class
Mixins是在多個類繼承關系里面重用代碼的一種方式。
為了使用mixin使用with關鍵字后面跟著一個或者多個mixin的名字。下面的例子就展示了使用mixins的兩個類。
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
想要實現一個mixin,需要創(chuàng)建一個類繼承自Object然后聲明一個無參構造。請使用mixin關鍵字而不是class關鍵字,除非你要把這個mixin也可以當作一個常規(guī)的類來使用。
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
有時候你可能想要限制可以使用mixin的類型,比如說,mixin可能依賴于一個可以調用某個方法的類,但是這個方法并沒有在mixin中定義。像下面的例子,你可以限制mixin的使用通過on這個關鍵字來指定需要的父類
class Musician {
// ...
}
mixin MusicalPerformer on Musician {
// ...
}
class SingerDancer extends Musician with MusicalPerformer {
// ...
}
在以上代碼中,只有繼承或者實現了Musician的類才可以使用MusicalPerformer這個mixin,因為SingerDancer繼承自Musician,SingerDancer可以使用MusicalPerformer這個mixin。
28.throw:拋出異常
29.catch:捕獲異常
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
30.false:就是false
31.new:和Java一樣,使用構造創(chuàng)建實例的時候,new可以省略
32.true:就是true
33.class:就是class
34.final:就是final
35.null:
未初始化的可空的類型的變量有個初始化的值是null,如果你沒有指定空安全,那么每一個變量都有一個可空的類型,甚至數字類型的變量的初始化的值也是null,因為數字和Dart里的其他類型一樣,都是對象。
int? lineCount;
assert(lineCount == null);
36.try:就是try
37.const:常量
38.finally:同Java
39.on:與try-catch配合使用,用來捕獲指定異常
40.typedef:type的別名,通常被稱為typedef是因為它是被關鍵字typedef聲明的,是一種推斷類型的簡潔的方式。
typedef IntList = List<int>;
IntList il = [1, 2, 3];
typedef ListMapper<X> = Map<X, List<X>>;
Map<String, List<String>> m1 = {}; // Verbose.
ListMapper<String> m2 = {}; // Same thing but shorter and clearer.
2.13之前,typedef只能在function上使用,要使用typedef新的特性,需要將dart升級到2.13以上
41.continue:同Java
42.for:
var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
for (final candidate in candidates) {
candidate.interview();
}
var collection = [1, 2, 3];
collection.forEach(print); // 1 2 3
```
43.operator:操作符
44.var:生命變量
45.default:與switch配合使用
46.get/set:
class Rectangle {
double left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// Define two calculated properties: right and bottom.
double get right => left + width;
set right(double value) => left = value - width;
double get bottom => top + height;
set bottom(double value) => top = value - height;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
>47.required:用在方法中表示參數必填
48.do/while:同Java
49.deferred:懶加載,在用到的時候在加載某些庫
import 'package:greetings/hello.dart' deferred as hello;
50.with:和mixin配合使用
51.yield:和sync配合使用
52.dynamic:未指定類型,直到運行時