學習Dart語言,必須將以下的概念熟記於心:
- 在dart語言中,一切皆為對象。所有的對象都是一個類的實例。甚至整數、函數、null也看做是對象。所有的對象都繼承於Object類
- 盡管Dart是強類型語言,但是變量的類型指定不一定要標明,因為Dart可以推斷出它的類型。比如說變量number就可以被推測出是int類型。如果你想明確表示這個變量不想被任何一個類型指定,那就使用特殊類型dynamic來表示。
- Dart語言支持通用類型,比如List<int>表示整數集列表,List<dynamic>表示元素集為任意類型對象的列表
- Dart支持頂級函數(如main()),以及綁定到類或對象的函數(分別是靜態方法和實例方法)。您還可以在函數中創建函數(嵌套函數或本地函數)。
- 類似的,Dart支持頂級變量,以及綁定到類或對象(靜態和實例變量)的變量。實例變量有時稱為字段或屬性。
- 有別於JAVA語言,dart語言中沒有public、protected和private這些關鍵字。在dart里面,如果標識符以下划線(_)開頭,那么它對其庫是私有的
- Dart里面的標志符號由
_
、字母和數字組成,只能以_
或者字母開頭 - Dart既有表達式(具有運行時值),也有語句(不具有運行時值)。比如傳統的表達式condition ? expr1 : expr2會有一個值,expr1或者expr2。相比較於if-else語句,則沒有值。一個語句通常包括一個或者多個表達式,但是一個表達式不能直接包含一個語句。
- Dart工具會向你發出兩種類型問題:警告和錯誤。警告則是指出你的代碼存在問題,但是不會阻止你正在執行的程序。錯誤則會發生在編譯時和運行時。編譯時的錯誤會完全阻止你代碼的運行。運行時錯誤導致代碼執行時引發異常。
變量
定義一個變量name並初始化一個String類型的值zeng:
var name = 'zeng'
這個name變量的類型會自動推斷出String類型,但是你也可以通過其他方法來改變類型。如果你不想讓一個變量僅僅受限為一個類型,你可以指定這個變量是Object或者dynamic類型,如下面的做法:
dynamic name = 'zeng'
還有一個做法就是顯示的聲明你即將定義的變量的類型,如:
String name = 'zeng'
如果你定義了一個變量而沒有初始化值,則這個變量有一個默認值null。即使變量是個數值類型(int),也是null,因為在dart語言中,一切皆為對象。
int a; assert(a == null)
final 和 const
如果你不想改變一個變量,使用final和const是最好的選擇。final變量只能設置一次 ,const變量是一個編譯時常量。頂層final或者class變量在第一次使用時就初始化 了。
定義一個final變量:
final name = 'zeng';//沒有一個類型聲明 final String nickName = 'lucky';
上面定義的final變量如果你改變他的值,則會報錯:
name = 'fan';//Error: a final variable can only be set once.
用const來定義一個編譯時的變量。如果const變量位於class級別,則將其標記為靜態const。在聲明變量的地方,將值設置為編譯時常量,如數字或字符串文字、常量變量或對常量進行算術運算的結果:
const a = 1000; const double b = 1.05 * a;
數據類型
Dart語言有以下七種內置數據類型
- numbers
- strings
- booleans
- lists (also known as arrays)
- maps
- runes (for expressing Unicode characters in a string)
- symbols
Numbers
Dart有兩種數值類型
int整數型
整數型的值不超過64位,取決於平台。如果在Dart VM平台,整數值的取值范圍是 -263 ~ 263 - 1。dart如果是編譯為javascript語言中javascript numbers,則取值為-253 ~ 253 - 1。
doubel浮點型
int和double類型都是數值型的子類型,這數值類型包括一些基本的運算符操作如 + 、- 、/ 和*,當然還有一些其他方法 abs()、ceil()、floor()。
int就是沒有小數點的數值。比如:
var x = 1; var y = 0xDEADBEEF;
而如果是有小數點的數值,它就是一個浮點型,比如:
var y = 1.1; var exponents = 1.42e5;
在Dart2.1版本中,在必要的時候,整數型的數值會自動轉換成浮點型的數值。比如
double z = 1; // Equivalent to double z = 1.0.
下面的是演示怎樣讓字符型轉換成數值型,反之亦然:
// String -> int var one = int.parse('1'); assert(one == 1); // String -> double var onePointOne = double.parse('1.1'); assert(onePointOne == 1.1); // int -> String String oneAsString = 1.toString(); assert(oneAsString == '1'); // double -> String String piAsString = 3.14159.toStringAsFixed(2); assert(piAsString == '3.14');
int類型也可進行按位操作(<<,>>)(&)、(|)
assert((3 << 1) == 6); // 0011 << 1 == 0110 assert((3 >> 1) == 1); // 0011 >> 1 == 0001 assert((3 | 4) == 7); // 0011 | 0100 == 0111
數字字面量是編譯時的常量。許多算術運算表達式也是編譯時的常量,只要他們的操作數是編譯時常量,計算結果是數字就行。比如:
const a = 100; const b = 10; const c = a * b;
String字符串
Dart字符串是一系列UTF-16代碼單元組成。你可以用單引號或者雙引號括起來組成一個字符串。
var s1 = 'use single quotes.'; var s2 = "use double quotes.";
通過 ${expression} 這個方法可以把表達式的值放入一個string中,如果這個表達式是個標識符,你也可以省略這個{}
var s = 'string interpolation'; assert('Dart has $s, which is very handy.' == 'Dart has string interpolation, ' + 'which is very handy.'); assert('That deserves all caps. ' + '${s.toUpperCase()} is very handy!' == 'That deserves all caps. ' + 'STRING INTERPOLATION is very handy!');
下面是連接字符串的方法:
var s1 = 'String ' 'concatenation' " works even over line breaks."; assert(s1 == 'String concatenation works even over ' 'line breaks.'); var s2 = 'The + operator ' + 'works, as well.'; assert(s2 == 'The + operator works, as well.');
如果你要寫多行的字符串,你可以使用三個單引號或者三個雙引號來標記:
var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";
可以通過r方法,讓你的字符串代碼原樣輸出:
var s = r'this is a test \n ,tell me';
Booleans布爾類型
Dart使用bool類型來表示布爾值。ture 和false是bool的兩個對象,同時這兩個也是編譯時常量
在dart語言中,我們不能使用javascript中的判斷語句,比如:
var a = ''; //在javascript中 if(a){ console.log('nice') } //但是在dart語言中,不能這樣進行判斷。而要使用下面的方法 if(a.isEmpty)
//檢查是否為null
var b ;
assert(b == null)
//檢查是否為NaN
var c = 0/0;
assert(c.isNaN)
Lists列表型
數組(array)幾乎是所有編程語言中最常見的集合。但在Dart語言中,數組就是List對象。
dart中的list就像是javascript中的Array。通過下面的例子了解dart中的list
var list = [1, 2, 3]; assert(list.length == 3); assert(list[1] == 2); list[1] = 1; assert(list[1] == 1);
Lists也有length,list中數據的表示方法也和數組一樣可以通過索引號碼來訪問特定的元素,比如List[1]。
Maps
通常來說,map是鍵值對類型的對象。key和value可以是任意類型的對象。但是不能出現相同的key,每個key只能出現一次,而相同的值可以多次出現。
var gifts = { // Key: Value 'first': 'partridge', 'second': 'turtledoves', 'fifth': 'golden rings' };
//新增一個key-value對
gifts['fourth'] = 'nice baby';
var nobleGases = { 2: 'helium', 10: 'neon', 18: 'argon', };
如上,key值中有了first,就不能再出現key為first的一項,不然會報錯。除了通過上面的字面量方法來創建map,也可以通過map構造器來創建對象
var gifts = Map(); gifts['first'] = 'partridge'; gifts['second'] = 'turtledoves'; gifts['fifth'] = 'golden rings'; var nobleGases = Map(); nobleGases[2] = 'helium'; nobleGases[10] = 'neon'; nobleGases[18] = 'argon';
如果你查找map對象里面不存在的key,則會返回一個null
var gifts = {'first': 'partridge'}; assert(gifts['fifth'] == null);
可以通過.length的方法獲取map中的鍵值對數量:
var gifts = {'first': 'partridge'}; gifts['fourth'] = 'calling birds'; assert(gifts.length == 2);
Functions函數集
bool isNoble(int atomicNumber) { return _nobleGases[atomicNumber] != null; }
聲明函數類型可以提升函數執行效率,如果省略這些類型,也是可以執行的:
isNoble(atomicNumber) { return _nobleGases[atomicNumber] != null; }
如果只有一個表達式,你可以簡寫為:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
函數可選參數
當調用一個函數,你需要指明參數paramName: value,比如:
enableFlags(bold: true, hidden: false);
當定義一個函數,你可以使用{param1,param2,....}來命名參數:
void enableFlags({bool bold, bool hidden}) {...}
如果是一個必須傳入的參數,則需要使用@required來指明參數:
const Scrollbar({Key key, @required Widget child})
我們也可以在[]中放置一個可選的參數:
String say(String from, String msg, [String device]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } return result; }
在上面的[]中的參數,可傳也可以不傳。如果我們想給一個參數一個默認的值,就可以使用如下的方法:
String say(String from, String msg, [String device = 'carrier pigeon', String mood]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } if (mood != null) { result = '$result (in a $mood mood)'; } return result; }
assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon');
當調用say函數時,沒有傳入device參數和mood參數,但是device參數有一個默認值‘carrrer pigeon’,所以不傳這個參數,則會默認把默認值放入到函數中運行。
main()函數
每個app都必須有main()函數,main()函數是作為app的入口函數。一個web app的入口函數如下:
void main() { querySelector('#sample_text_id') ..text = 'Click me!' ..onClick.listen(reverseText); }
注:..
是一種級聯操作符,它返回調用者本身,這樣就可以連續調用同一個對象上的多個方法,實現鏈式操作!
函數可以作為另一個函數的參數運行,如
void printElement(int element) { print(element); } var list = [1, 2, 3]; // Pass printElement as a parameter. list.forEach(printElement);
類型檢查操作符
as、 is、 is!
比如:
if (emp is Person) { // Type check emp.firstName = 'Bob'; }
分配符
// Assign value to a a = value; // Assign value to b if b is null; otherwise, b stays the same b ??= value;