Dart語言特性:
- 在Dart中,一切都是對象,一切對象都是class的實例,哪怕是數字類型、方法甚至null都是對象,所有的對象都是繼承自Object
- 雖然Dart是強類型語言,但變量類型是可選的因為Dart可以自動推斷變量類型
- Dart支持范型,List<int>表示一個整型的數據列表,List<dynamic>則是一個對象的列表,其中可以裝任意對象
- Dart支持頂層方法(如main方法),也支持類方法或對象方法,同時你也可以在方法內部創建方法
- Dart支持頂層變量,也支持類變量或對象變量
- 跟Java不同的是,Dart沒有public protected private等關鍵字,如果某個變量以下划線(_)開頭,代表這個變量在庫中是私有的
- Dart中變量可以以字母或下划線開頭,后面跟着任意組合的字符或數字
變量與常量:
void main(){ // 沒有明確類型,編譯的時候根據值明確類型 var name0 = "字符串可以是雙引號"; var name1 = '字符串也可以是單引號'; //如果對象沒有明確的類型,可使用Object或dynamic關鍵字。 Object name2 = '張三';//所有類都繼承於object dynamic name3 = '李四';//dynamic不是在編譯時候確定實際類型的, 而是在運行時。 String name4 = 'Bob';// 顯示聲明類型 // number var a = 0; // 自動推斷類型 int b = 1; double c = 0.1; // string var s1 = 'hello'; String s2 = "world"; // boolean var real = true; bool isReal = false; // lists var arr = [1, 2, 3, 4, 5]; List<String> arr2 = ['hello', 'world', "123", "456"]; List<dynamic> arr3 = [1, true, 'haha', 1.0]; arr3.forEach((item){ print("item = $item"); }); // maps var map = new Map(); map['key'] = 'value'; var map2 = {"key1":"value1" , "key2":"value2"}; //遍歷 map2.forEach((key,value){ print("key = ${key},value = ${value}"); }); }
運行效果:

常量Final 和 Const的用法:
final和const的區別:
區別一:final 要求變量只能初始化一次,並不要求賦的值一定是編譯時常量,可以是常量也可以不是。而 const 要求在聲明時初始化,並且賦值必需為編譯時常量。
區別二:final 是惰性初始化,即在運行時第一次使用前才初始化。而 const 是在編譯時就確定值了。
void main(){ //被 final 或 const 修飾的變量無法再去修改其值。 final String str = "string" + '拼接 string2'; const String str2 = 'string';//被const修飾的變量是一個編譯時常量 // flnal 或者 const 不能和 var 同時使用 //final var str = '報錯'; 這樣寫 報錯 const Map map = {"key1":"value1"}; const List list = [1,2];//const修飾的 List 對象地址不可變,集合長度也不可變(編譯時就確定了) final List list2 = new List();//final修飾的 List 對象地址不可變,集合長度可變 list2.add("運行時常量,可添加"); // 注意: [] 創建的是一個空的list集合 // const []創建一個空的、不可變的列表。 var varList = const []; // 對象地址可變,但是集合長度不可變 final finalList = const []; // 兩者都不可變 const constList = const []; // 兩者都不可變 // varList.add("添加會報錯"); // 可以更改非final,非const變量的地址 varList = new List(); // finalList = new List();//報錯 不可變 } class a { //常量如果是類級別的,需要使用 static const static const speed = 100; }
運算符:

Dart里面比較有代表性的以及有特點的一些運算符相關用法。
跟kotlin里一樣的?.
String a = null; //如果a 為 null, a?.length = null print(a?.length);//輸出:null String b = "b"; print(b?.length);//輸出:1
級聯符號..
//相當於java的鏈式調用, .. 返回對象本身 String s = (new StringBuffer() ..write('test1 ') //write方法 返回的是 void ..write('test2 ') ..write('test3 ') ..write('test4 ') ..write('test5') ).toString(); print(s); //輸出: test1 test2 test3 test4 test5
?? 三目運算符的一種形式
//普通三元運算符 int a = 10; var values = a > 5 ? a : 0; print(values);//輸出: 10 // ?? 操作符, expr1 ?? expr2 表示如果expr1非空,則返回其值; 否則返回expr2的值。 print('${a ??= 3}'); //輸出: 10
~/ 除法,返回一個整數結果,其實就是取商。
var result1 = 15 / 7;// 除法 print(result1); // 結果是:2.142857... var result2 = 15 ~/ 7;//取 商 print(result2); // 結果是:2 var result3 = 15 % 7; //取 余數 print(result3); // 結果是:1
as、is與is!
as 判斷屬於某種類型is 如果對象具有指定的類型,則為trueis! 如果對象具有指定的類型,則為false
String str = "str"; bool a = true; //is 輸出是true 或者 false print(str is bool); // false print(str is! bool); // true //as 輸出是一個對象 var asStr = str as String; print(asStr?.length);//輸出:3
控制流程語句 if else for循環 switch while
控制流程語句和Java語言差不多,下面只試下標記
for循環跳到指定標記處:


if語句中跳出代碼塊:
return就不測試了,跟java一樣


異常:
void main() { try { method1(); }on FormatException catch (e) { //判斷 是否是 指定的FormatException異常 print('main() 拿到異常 ${e.runtimeType} 異常信息:${e.message}'); }catch (e,s) {//第一個參數是拋出的異常,第二個是堆棧跟蹤(StackTrace對象)。 print('main() 拿到異常 ${e.runtimeType}}'); }finally { print("finally 結束"); } print("------------------------"); try { method2(); }catch (e,s) {//第一個參數是拋出的異常,第二個是堆棧跟蹤(StackTrace對象)。 print('main() 拿到異常 ${e.runtimeType} 異常信息:${s}'); } } void method1() { try { dynamic foo = true; print(foo++); // 運行時異常 } catch (e) { print('異常了 ${e.runtimeType}'); throw new FormatException("自己拋出異常"); } } void method2() { try { dynamic foo = true; print(foo++); // 運行時異常 } catch (e) { print('異常了 ${e.runtimeType}'); rethrow; // 傳遞異常,允許調用者獲取exception. } }
輸出日志:

方法:
方法的定義:
void main() { print(method1("method1")); print(method2("method2")); print(method3("method3")); //函數 也是 一個對象 使用 Function接收 Function function = method1;//接收方法 print(function("aaa"));//執行方法 } String method1(String str) { return str; } // 返回類型 可省略 method2(String str) { return str; } //返回 null method3(String str) { print(str); }
輸出日志:

方法的傳參方式:
void main() { method1("第一種傳參方式"); method2(str: "第二種傳參方式"); method3(str: "第三種傳參方式"); } void method1(String str) { print(str); } void method2({str: String}) { print(str); } void method3({String str}) { print(str); }
默認參數,位置參數:
void main() { method1(1); method1(1,"傳參name","傳參name2");// [] 括起來的,直接傳, 按照參數位置定值 method1_1(1); method1_1(1,name2: "傳參name2", name: "傳參name");// {} 括起來的,需要帶參數名稱,傳參位置隨意 method2(2); method2(2); method2(2,"傳參name"); method2_2(2); method2_2(2,name: "傳參name"); } /** * []括起來的參數是函數的位置參數,代表該參數可傳可不傳, * 位置參數只能放在函數的參數列表的最后面 */ String method1(int age, [String name,String name2]) { print("age = $age" + ",name = $name" + ",name2 = $name2"); } /** * {} 括起來的參數 可傳 可不傳 還可以寫默認參數 */ String method1_1(int age, {String name, String name2}){ print("age = $age" + ",name = $name" + ",name2 = $name2"); } //帶默認值 String method2(int age, [String name = "默認值"]) { print("age = $age" + ",name = $name"); } String method2_2(int age, {String name = "默認值"}){ print("age = $age" + ",name = $name"); }
匿名方法、方法作為參數:
/** *日志打印: 第一種形式 第二種形式 第三種形式(匿名方法) */ main() { //第一種方法 Function function = method; function("第一種形式"); //簡寫 省略方法名了 Function function2 = (String str){ print(str); }; function2("第二種形式"); //匿名了 取消接收對象 test((String param) { print(param);//接收方法 }); } // 方法的參數為 一個方法 test(Function aaa) { aaa("第三種形式(匿名方法)");//執行方法 } method(String str){ print(str); }
類:
類的定義與構造方法
main() { var testChild = new TestChild(); //通過 命名構造 來創建對象 Test test = new Test.onlyX(2); test.y = 1; test.setX = 2; print(test.getX); } class Test{ int x;//成員變量 int y; /** * Dart提供了set和get關鍵字幫助我們更高效的訪問成員變量. * * 可以把它當做一個成員方法來看 */ int get getX { return x; } set setX(int value) { x = x + value; } //Dart不像java可以使用多個同名不同參數構造。但是Dart提供了命名構造 Test(this.x,this.y){ print('x=${x}, y = ${y}'); } // 命名構造 Test.onlyX(int x) { this.x = x; y = 10; print('x=${x}, y = ${y}'); } } /** * Dart中使用extends關鍵字做類的繼承,如果一個類只有命名的構造方法, * 在繼承時需要調用父類的命名構造方法 */ class TestChild extends Test{ TestChild() : super(0, 0){ print('這是 TestChild 類的空參構造'); } }
類的繼承
類的繼承跟java一樣
abstract class Doer { // 抽象方法,沒有方法體,需要子類去實現 void doSomething(); // 普通的方法 void greet() { } } class EffectiveDoer extends Doer { // 需要實現父類的抽象方法 @override void doSomething() { } //重寫父類的方法 @override void greet() { super.greet(); } }
類的實現
/** * 日志: Hello, Bob. I am Person. Hi Bob. Do you know who I am? */ main() { print(greetBob(new Person('Person')));//調用Person 的 greet方法 print(greetBob(new Impostor()));//調用Impostor 的 greet方法 } String greetBob(Person person){ return person.greet('Bob'); } class Person { final _name; Person(this._name); String greet(String who) => 'Hello, $who. I am $_name.'; } /** * Impostor實現Person接口 (隱式接口) * 接口是更純粹的抽象,使用接口時必須實現其定義的所有成員.(除了構造方法不能繼承) */ class Impostor implements Person { @override get _name => "Person的實現類"; @override String greet(String who) => 'Hi $who. Do you know who I am?'; }
枚舉類
來之文檔中的截圖
mixin 類的混合
//作為 mixin的類 不能定義構造方法 class A { a() { print("A's a()"); } } class B { b() { print("B's b()"); } } // 使用with關鍵字,表示類C是由類A和類B混合而構成 class C with A,B,D { //C 擁有 A B D 的特性 } // 不能通過new 來創建D對象 mixin D { void method() { print('mixin D 方法'); } } main() { C c = new C(); c.a(); // A's a() c.b(); // B's b() c.method();// mixin D 方法 }
導入庫import:
異步:
import 'package:http/http.dart' as http; import 'package:http/http.dart'; void main(){ getData().then((String data){ print(data); }); } /** * async 代表該方法是異步的 * 異步函數,他的返回值將是一個Future */ Future<String> getData() async { //await 關鍵字聲明運算為延遲執行,然后return運算結果 await可以多次使用 Response response = await http.get("http://www.baidu.com"); print("請求成功:${response.body.substring(0,10)}"); return response.body; }
上面例子中需要引入第三方包 http, 導包方式

第三方庫搜索地址:https://pub.dev/
Dart對集合List的操作:


