Dart 操做符和主流語言的操做符相似, 只要有一門經常使用語言, 對 Dart 掌握也是很快的bash
Dart 和之前介紹的 Kotlin 相似, 也提供操做符重載功能框架
Dart 支持下面經常使用的數學操做符:less
操做符 | 意義 |
---|---|
+ | 加號 |
- | 減號 |
-expr | 一元操做符,負號 |
* | 乘號 |
/ | 除號 |
~/ | 除號,返回一個整型 |
% | 取餘 |
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder
複製代碼
須要注意的是兩個整型相除是返回一個 double
類型的值,而不是像 Java 同樣返回一個整型,若是須要返回整型可使用 ~/
ide
Dart 還支持前綴後綴自增自減操做符:函數
操做符 | 意義 |
---|---|
++var | var = var + 1 (整個表達式的值是 var + 1) |
var++ | var = var + 1 (整個表達式的值是 var) |
--var | var = var – 1 (整個表達式的值是 var – 1) |
var-- | var = var – 1 (整個表達式的值是 var) |
下面的例子完美解釋了先後綴自增自減的差別:工具
var a, b;
a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1
a = 0;
b = a++; // Increment a AFTER b gets its value.
assert(a != b); // 1 != 0
a = 0;
b = --a; // Decrement a before b gets its value.
assert(a == b); // -1 == -1
a = 0;
b = a--; // Decrement a AFTER b gets its value.
assert(a != b); // -1 != 0
複製代碼
操做符 | 意義 |
---|---|
== | 相等 |
!= | 不等 |
> | 大於 |
< | 小於 |
>= | 大於等於 |
<= | 小於等於 |
須要注意的是,比較斷兩個對象內容是否相等使用 ==
, 比較兩個對象是不是同一個對象使用 identical()
函數性能
比較兩個對象內容是否相等,須要重載操做符 ==
, 如何重載操做符後面會介紹學習
操做符 | 意義 |
---|---|
as | 類型強轉 |
is | 判斷某個對象是特定類型 |
is! | 判斷某個對象不是特定類型 |
// 判斷 emp 是不是 Person 類型
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
// 將 emp 強制轉換爲 Person, 若是 emp 不是 Person 類型則會拋出異常
(emp as Person).firstName = 'Bob';
複製代碼
操做符 | 意義 |
---|---|
!expr | 布爾取反 |
|| | 邏輯或 |
&& | 邏輯與 |
if (!done && (col == 0 || col == 3)) {
// ...Do something...
}
複製代碼
操做符 | 意義 |
---|---|
& | 按位與 |
| | 按位或 |
^ | 按位異或 |
~expr | 按位非 |
<< | 左移 |
>> | 右移 |
操做符 | 意義 |
---|---|
= | 賦值(a = b) |
–= | a -= b 和 a = a - b 等價 |
/= | a /= b 和 a = a / b 等價 |
%= | a %= b 和 a = a % b 等價 |
>>= | a >>= b 和 a = a >> b 等價 |
^= | a ^= b 和 a = a ^ b 等價 |
+= | a += b 和 a = a + b 等價 |
*= | a *= b 和 a = a * b 等價 |
~/= | a ~/= b 和 a = a ~/ b 等價 |
<<= | a <<= b 和 a = a << b 等價 |
&= | a &= b 和 a = a & b 等價 |
|= | a |= b 和 a = a | b 等價 |
Dart 提供了兩個操做符來簡化特定狀況的 if-else
語句開發工具
condition ? expr1 : expr2ui
若是 condition
是 true, 返回 expr1
, 不然返回 expr2
var visibility = isPublic ? 'public' : 'private';
複製代碼
expr1 ?? expr2
若是 expr1
不爲 null, 返回 expr1
, 不然返回 expr2
String playerName(String name) => name ?? 'Guest';
複製代碼
例如咱們能夠把下面的函數使用條件表達式簡化下:
String playerName(String name) {
if (name != null) {
return name;
} else {
return 'Guest';
}
}
// 能夠簡化成以下:
String playerName(String name) => name != null ? name : 'Guest';
String playerName(String name) => name ?? 'Guest';
複製代碼
嚴格的講, 級聯符號(cascade notation)
不是一個操做符, 而是 Dart 的一個語法糖, 它不只可讓開發者鏈式調用函數, 還能夠鏈式訪問屬性, 因此當咱們須要頻繁訪問某個對象的屬性和函數:
class Person {
int age = 0;
String name = "chiclaim";
void sayHello() {
print("hello , my name is $name");
}
}
main(){
var p = Person();
p.age = 1;
p.name = "johnny";
p.sayHello();
}
複製代碼
咱們可使用級聯操做符改形成以下形勢:
main() {
Person()
..age = 1
..name = "johnny"
..sayHello();
}
複製代碼
除此之外, 還能夠級聯嵌套, 如:
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
複製代碼
須要注意的是, 不能在一個 void
函數後面開始你的級聯操做:
var sb = StringBuffer();
sb.write('foo')
..write('bar');
複製代碼
可是能夠在調用 StringBuffer
構造函數後面開始你的級聯操做:
StringBuffer()
..write('foo')
..write('bar');
複製代碼
操做符 | 意義 |
---|---|
() | 函數調用 |
[] | 集合元素訪問 |
. | 成員訪問 |
?. | 成員訪問, 左邊的操做符能夠爲null, foo?.bar 若是 foo 爲空那麼整個表達式爲null |
Dart 提供操做符重載功能,容許開發者重載一下操做符:
操做符 | 操做符 | 操做符 | 操做符 |
---|---|---|---|
< | + | | | [] |
> | / | ^ | []= |
<= | ~/ | & | ~ |
>= | * | << | == |
– | % | >> |
操做符重載的語法格式爲: 返回類型 operator
操做符 (參數)
下面來看下官方一個操做符重載的例子:
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);
// 重載 == 操做符
bool operator ==(other) => other is Vector
&& runtimeType == other.runtimeType
&& x == other.x && y == other.y;
}
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
函數, 相似 Java 中重載了 equals
函數,最好也重載 hashCode
函數是同樣的, 由於對象的 hash
值決定對象的存儲位置
@override
int get hashCode => x.hashCode ^ y.hashCode;
複製代碼
Dart 支持 if 語句和可選的 else 語句
if (isRaining()) {
print("raining");
} else if (isSnowing()) {
print("snowing");
} else {
print("unknown");
}
複製代碼
Dart 不只支持標準的 for 循環:
for (var i = 0; i < 5; i++) {
}
複製代碼
還支持 for-in
那些實現了 Iterator
接口的類(如List/Set):
var collection = [0, 1, 2];
for (var x in collection) {
print(x); // 0 1 2
}
複製代碼
經過上一篇文章(三)Flutter學習之Dart函數的介紹知道
Dart Closures
可以訪問自身做用域內的變量, 哪怕這個變量是外部傳遞給 Closure 的 如:
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
// 輸出
1
2
複製代碼
可是在 JavaScript
中會輸出兩個 2
while/do-while/break/continue
和其餘語言沒有什麼區別, 在這裏就不贅述了
Switch 語句能夠接受 整型、字符串 、枚舉
或者 編譯時常量
, 而後使用 ==
進行比較, 下面看下常量的比較:
class Person {
final String id;
const Person(this.id);
}
const p = Person("001");
const p1 = Person("001");
const p2 = Person("003");
switch (p) {
case p1:
print(p1.id);
break;
case p2:
print(p2.id);
break;
default:
print("unknown");
}
複製代碼
若是 case
子句不是空, 要以 break/return/throw/continue
結尾, 不然會報錯
若是想要 case
子句之間 fall-through
的話, 將 case
子句爲空便可
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
case 'NOW_CLOSED':
print("NOW_CLOSED");
break;
default:
print("UNKNOWN");
}
複製代碼
還可使用 continue
的方式 fall-through
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
print("CLOSED");
continue nowClosed;
nowClosed:
case 'NOW_CLOSED':
print("NOW_CLOSED");
break;
default:
print("UNKNOWN");
}
// 輸出
CLOSED
NOW_CLOSED
複製代碼
在開發階段, 咱們可使用斷言語句 assert(condition, optionalMessage);
來中斷程序的正常執行, 當 condition
爲 false
的時候(拋出 AssertionError
異常); 若是 condition
爲 true
, 則繼續執行程序的下一行代碼. 例如:
// Make sure the value is less than 100.
assert(number < 100);
// Make sure this is an https URL.
assert(urlString.startsWith('https'));
assert(urlString.startsWith('https'),
'URL ($urlString) should start with "https".');
複製代碼
斷言何時生效呢?這取決於你使用的工具和框架:
debug
模式啓用斷言dartdevc
, 默認是開啓斷言dart
、dart2js
等工具支持命令行來啓用斷言: --enable-asserts
在生產環境的代碼, 斷言語句將會被忽略, 斷言的 condition
表達式不會被執行,因此不用擔憂性能問題
Dart 提供了 throw, rethrow, try, catch, on, finally
關鍵字讓開發者可以拋出和捕獲異常
和 Java
不一樣的是, Dart 中全部的異常都是 unchecked
異常, 也就是說編譯器不會強制開發者去捕獲任何異常, 除非你有這個須要
Dart 提供了兩個類異常: Exception
和 Error
, Dart 不只能夠拋出異常還能夠拋出任何不爲 null
的對象:
// 拋出異常
throw FormatException('Expected at least 1 section');
// 拋出不爲 null 的對象
throw 'Out of llamas!';
複製代碼
雖然 Dart 容許咱們拋出一個不爲 null 的普通對象,可是官方仍是建議咱們拋出的異常繼承自 Exception
或 Error
介紹完了 throw
關鍵字,咱們來看下 catch
和 on
和 關鍵字:
catch
和 on
都是用來捕獲異常:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 捕獲一個特定的異常
buyMoreLlamas();
} on Exception catch (e) {
// 捕獲全部繼承自 Exception 的異常,並拿到異常對象
print('Unknown exception: $e');
} catch (e) {
// 捕獲全部異常
print('Something really unknown: $e');
}
複製代碼
可見, on
關鍵字用於指定捕獲特定的異常, catch
關鍵字用於拿到異常對象
catch
關鍵字除了能夠拿到異常對象, 還能夠拿到異常的 堆棧
信息, 如:
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
複製代碼
通常狀況下, 使用了 on, catch
關鍵字來捕獲異常, 異常會中止傳播, 若是須要異常繼續傳播可使用 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}.');
}
}
複製代碼
最後介紹 Dart
異常處理的最後一個關鍵字 finally
finnaly
關鍵字很簡單 , 就是不論是否拋出異常 finally
子句必定會執行:
try {
breedMoreLlamas();
} finally {
// 就算拋出異常(程序中斷執行), finnaly 也會先執行
cleanLlamaStalls();
}
try {
breedMoreLlamas();
} catch (e) {
// 捕獲異常
print('Error: $e');
} finally {
// 執行 finally 子句
cleanLlamaStalls(); // Then clean up.
}
複製代碼
關於 Dart
的 操做符, 控制流, 異常處理
就介紹完畢
下面是個人公衆號,乾貨文章不錯過,有須要的能夠關注下,有任何問題能夠聯繫我: