Dart 關鍵字【2】
想要寫好Flutter
,那麼對Dart
的基本關鍵字的掌握是必不可少的,今天就再探究一下其他的關鍵字。
as is si!
as
is
is!
,運算子用於執行時處理型別檢查:
當obj
實現了T
的介面時,obj is T
是true
,obj as T
可以將obj
型別轉換成T
型別:
class Person { void play(){ print('person'); } } class PersonSub extends Person{} class Person2 { void play(){ print('person2'); } } Person person = PersonSub(); if(person is Person2){ (person as Person2).play(); } if(person is PersonSub){ (person as PersonSub).play(); }
當person
型別是Person2
執行第一個if
函式,如果直接(person as Person2).play();
,則會崩潰,每次轉換型別的時候,提交校驗a is T
是有必要的。
enum
列舉型別也稱為 enumerations
或 enums
, 是一種特殊的類,用於表示數量固定的常量值。
throw catch on final rethrow
捕獲異常可以避免異常繼續傳遞(除非重新丟擲(rethrow
)異常)。 可以通過捕獲異常的機會來處理該異常:
try { breedMoreLlamas(); } on OutOfLlamasException { buyMoreLlamas(); }
通過指定多個 catch
語句,可以處理可能丟擲多種型別異常的程式碼。 與丟擲異常型別匹配的第一個 catch
語句處理異常。 如果 catch
語句未指定型別, 則該語句可以處理任何型別的丟擲物件:
try { breedMoreLlamas(); } on OutOfLlamasException { // 一個特殊的異常 buyMoreLlamas(); } on Exception catch (e) { // 其他任何異常 print('Unknown exception: $e'); } catch (e) { // 沒有指定的型別,處理所有異常 print('Something really unknown: $e'); }
如上述程式碼所示,捕獲語句中可以同時使用 on
和 catch
,也可以單獨分開使用。 使用 on 來指定異常型別, 使用 catch
來 捕獲異常物件。
catch()
函式可以指定1到2個引數, 第一個引數為丟擲的異常物件, 第二個為堆疊資訊 ( 一個 StackTrace
物件 )。
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
如果僅需要部分處理異常, 那麼可以使用關鍵字 rethrow
將異常重新丟擲。
void misbehave() {
try {
dynamic foo = true;
print(foo++); // Runtime error
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // Allow callers to see the exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
不管是否丟擲異常, finally
中的程式碼都會被執行。 如果 catch
沒有匹配到異常, 異常會在 finally
執行完成後,再次被丟擲:
try {
breedMoreLlamas();
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
任何匹配的 catch
執行完成後,再執行 finally
:
try {
breedMoreLlamas();
} catch (e) {
print('Error: $e'); // Handle the exception first.
} finally {
cleanLlamaStalls(); // Then clean up.
}
factory
當執行建構函式並不總是建立這個類的一個新例項時,則使用 factory
關鍵字。 例如,一個工廠建構函式可能會返回一個 cache
中的例項, 或者可能返回一個子類的例項。
以下示例演示了從快取中返回物件的工廠建構函式:
class Logger {
final String name;
bool mute = false;
// 從命名的 _ 可以知,
// _cache 是私有屬性。
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
const
使用過程中從來不會被修改的變數, 可以使用 final 或 const, 而不是 var 或者其他型別, Final 變數的值只能被設定一次; Const 變數在編譯時就已經固定 (Const 變數 是隱式 Final 的型別.) 最高階 final 變數或類變數在第一次使用時被初始化。
提示: 例項變數可以是 final 型別但不能是 const 型別。 必須在建構函式體執行之前初始化 final 例項變數 —— 在變數宣告中,引數建構函式中或建構函式的初始化列表中進行初始化。
建立和設定一個 Final 變數:
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
final
不能被修改:
name = 'Alice'; // Error: 一個 final 變數只能被設定一次。
如果需要在編譯時就固定變數的值,可以使用 const 型別變數。 如果 Const 變數是類級別的,需要標記為 static const。 在這些地方可以使用在編譯時就已經固定不變的值,字面量的數字和字串, 固定的變數,或者是用於計算的固定數字:
const bar = 1000000; // 壓力單位 (dynes/cm2)
const double atm = 1.01325 * bar; // 標準氣壓
operator
重寫運算子,下面的運算子可以被重寫。
< | + | | | [] |
---|---|---|---|
> | / | ^ | [] |
<= | ~/ | & | ~ |
>= | * | << | == |
– | % | >> |
提示: 你可能會被提示 != 運算子為非可過載運算子。 因為 e1 != e2 表示式僅僅是 !(e1 == e2) 的語法糖。
下面示例演示一個類重寫 + 和 - 操作符:
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
// 運算子 == 和 hashCode 部分沒有列出。 有關詳情,請參考下面的註釋。
// ···
}
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
assert(v + w == Vector(4, 5));
assert(v - w == Vector(0, 1));
}
如果要重寫 == 操作符,需要重寫物件的 hashCode getter 方法。 重寫 == 和 hashCode 的例項,參考 Implementing map keys.
part part of
covariant
Function
Dart 是一門真正面向物件的語言, 甚至其中的函式也是物件,並且有它的型別 Function 。 這也意味著函式可以被賦值給變數或者作為引數傳遞給其他函式。 也可以把 Dart 類的例項當做方法來呼叫。 有關更多資訊,參考 Callable classes.
已下是函式實現的示例:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
雖然在 Effective Dart 中推薦 公共API中宣告型別, 但是省略了型別宣告,函式依舊是可以正常使用的:
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
如果函式中只有一句表示式,可以使用簡寫語法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
=> expr 語法是 { return expr; } 的簡寫。 => 符號 有時也被稱為 箭頭 語法。
提示: 在箭頭 (=>) 和分號 (