Flutter 是由Google開發的UI工具包,是採用了 Dart 來編寫的框架和 widget。
因此咱們要學習Flutter開發,就有必要了解dart語言,不說精通,至少得對dart的一些語法有一些瞭解。
其實若是你之前有過其它程序開發經驗,很快便能掌握dart語法。
和javascript相比, dart是一門強類型的語言,Dart 綜合了動態語言和靜態語言的特性。javascript
聲明變量前端
// 聲明變量並賦值 var name = 'Bob' // 若是聲明時沒有賦值, 默認值爲null String name; // name的值爲null
final 與constjava
若是你之後不打算修改一個變量,使用 final 或者 const。 一個 final 變量只能賦值一次;一個 const 變量是編譯時常量。python
const age = 123; // const 在代碼編譯時就已經肯定了變量的值 final age; // 默認爲null age = 123; // 第一次賦值爲123 age = 234; // Error 報錯, final只能賦值一次
const 關鍵字不只僅只用來定義常量。 有時也能夠用來建立不變的值, 還能定義構造函數爲 const 類型的,這種類型 的構造函數建立的對象是不可改變的。express
int x = 1; double y = 2.1; // x = '222' // 報錯,x是整數
數字和字符串這間的轉換編程
// String -> int int strToInt = int.parse('1'); // String -> double double strToDouble = double.parse('1.1'); // int -> String String intToStr = 1.toString(); // double -> String String doubleToStr = 3.14159.toStringAsFixed(2);
Dart 字符串是 UTF-16 編碼的字符序列。 可使用單引號或者雙引號來建立字符串json
var s1 = 'Single quotes work well for string literals.'; var s2 = "Double quotes work just as well."; // 在字符串中使用表達式 ${expression},若是表達式是個變量,能夠省去{}。 // 相似JS裏的 `abc${var}` var s = 'string interpolation'; var p = '這是一個表達式${s}'; var k = '這是一個表達式$s'; // 和js同樣,可使用+鏈接多個字段串 var t = s + p + k;
使用三個單引號或者雙引號也能夠 建立多行字符串對象segmentfault
var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";
Dart 有一個名字爲 bool 的類型。 只有兩個對象是布爾類型的:true 和 false 所建立的對象, 這兩個對象也都是編譯時常量。數組
通俗地講就是dart判斷bool值就是隻能用true和false,像JS的0, 1, null等都能判斷表達式真假,dart不能。緩存
var name = 'Bob'; if (name) { // 這裏dart會拋出一個異常, 表示name變量不是一個布爾值。 // javascript 能夠這樣判斷, dart 不能 print('Bob'); }
至關於JS裏的數組,表示爲有序的集合。
至關於JS裏的對象字面量, python裏的字典.
Map 是一個鍵值對相關的對象。 鍵和值能夠是任何類型的對象。
var gifts = { // Keys Values 'first' : 'partridge', 'second': 'turtledoves', 'fifth' : 'golden rings' }; // 使用 Map 構造函數也能夠實現一樣的功能 var gifts = new Map(); gifts['first'] = 'partridge'; gifts['second'] = 'turtledoves'; gifts['fifth'] = 'golden rings';
runes 表明字符串的 UTF-32 code points。
略過
在Dart中, function是一種類型爲 Function 的對象,這意味着function能夠賦值給變量,也能夠當作其餘function的參數。 這和Javascript中function比較像。
對於只有一個表達式的function, 可使用 =>
形式 縮寫:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
dart語言函數(方法)有兩種參數: 必需的和可選的。 必需的參數在參數列表前面, 後面是可選參數。
可選參數又能夠分爲命名參數或者基於位置的參數,可是這兩種參數不能同時當作可選參數。
參數若是沒有設置默認值, 默認值爲null。
// 可選命名參數 enableFlags({bool bold, bool hidden}) { // ... } // 可選位置參數 把一些方法的參數放到 [] 中就變成可選 位置參數了 String say(String from, String msg, [String device]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } return result; }
// 參數傳遞簡單的數字 void main() { int k = 5; print(k); test(k); print(k); } void test(int a) { a = 77; print(a); } // 返回的結果是 5 77 5 // 函數傳遞map void main() { Map<int, String> k = { 1: '123', 2: '234' }; print(k); test(k); print(k); } void test(Map a) { a[1] = 'kkkk'; print(a); } // 返回的結果是 {1: 123, 2: 234} {1: kkkk, 2: 234} {1: kkkk, 2: 234}
具體原理也能夠能夠參照 https://blog.csdn.net/bbdxf/a...
- var a = 10;這種賦值語法的含義是a是指向一個內存對象10的引用(ref).
- var a = 10; var b=a; 則a,b都指向同一個內存對象,即引用同一個內存對象。可是a,b之間沒有任何聯繫。
- 在2的狀況下,修改a指向對象的值,b也會跟着改。(矛盾點也在這裏!)
- 可是,Dart中不是全部的對象均可以修改的(mutable or immutable),其中number,String,bool等都是不可變類型,每次修改都是產生一個新的對象。而其餘大部分對象都是mutable, 因此第3條的狀況在面對immutable對象會表現不一致。
看起來和JS的函數參數傳遞是差很少的。按照JS傳參理解的話就是:
簡單的如數字,字符串,bool 是值傳遞。在函數內部對參數變量從新賦值,不會改變函數做用域外的值。Lists, Maps, Functions, 對象等是按引用傳遞。在函數內部對參數變量從新賦值,函數做用域外的值也會相應地跟着改變
這節咱們主要關注下那些與JS語法中不同的那些操做符。其它的像 +, -, * , / , >, <, = ,%, ++, -- 等 這些操做符和js裏徹底是同樣的。
// 1 整除 ~/ // 至關於除數取整數部分, assert(5 ~/ 2 == 2) // 至關於JS裏的 Math.floor(5/2) assert(5 ~/ 3 == 1) // as 類型轉換 // is 若是對象是指定的類型返回 True // is! 若是對象是指定的類型返回 False // 只有當 obj 實現了 T 的接口, obj is T 纔是 true。 if (emp is Person) { // Type check emp.firstName = 'Bob'; } (emp as Person).firstName = 'Bob'; // 若是 emp 是 null 或者不是 Person 類型, 則第一個示例使用 is 則不會執行條件裏面的代碼,而第二個狀況使用 as 則會拋出一個異常。 // 賦值操做符 // ??= 有點像是JS裏 || 表達式賦值 a = value; // 給 a 變量賦值 b ??= value; // 若是 b 是 null,則賦值給 b; // 若是不是 null,則 b 的值保持不變 // 條件表達式 ?? // 至關於js裏的&& // 級聯操做符 .. // 級聯操做符 (..) 能夠在同一個對象上 連續調用多個函數以及訪問成員變量。 // 條件成員訪問 ?. 和 . 相似,可是左邊的操做對象不能爲 null,例如 foo?.bar // 若是 foo 爲 null 則返回 null,不然返回 bar 成員 querySelector('#button') // Get an object. ..text = 'Confirm' // Use its members. ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); // 和上面的代碼和下面的代碼功能同樣: var button = querySelector('#button'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!'));
流程控制和其它編程語言的基本上是同樣的。
須要注意的是條件表達式(if...else...)的判斷條件只能是True和false。
Dart 提供了 Exception 和 Error 類型, 以及一些子類型。你還 能夠定義本身的異常類型。 Dart 代碼能夠 拋出任何非 null 對象爲異常,不只僅是實現了 Exception 或者 Error 的對象。
Throw 拋出異常
try...catch 捕獲異常
Finally 要確保某些代碼執行,無論有沒有出現異常都須要執行
class Point { // 類屬性 num x; num y; // this 關鍵字指當前的實例。 // 構造函數 Point(this.x, this.y) // 至關於 //Point(num x, num y) { // this.x = x; // this.y = y; //} // 命名構造函數 Point.fromJson(Map json) { x = json['x']; y = json['y']; print('in Super Classes'); } // 方法 num distanceTo(Point other) { var dx = x - other.x; var dy = y - other.y; return sqrt(dx * dx + dy * dy); } // Getter, setters // 每一個實例變量都隱含的具備一個 getter, 若是變量不是 final 的則還有一setter。 // 你能夠經過實行 getter 和 setter 來建立新的屬性, 使用 get 和 set 關鍵字定義 getter 和 setter } // 調用超類構造函數 class ChildClass extends Point { // 採用 ChildClass.fromJson(Map json) : super.fromJson(data) { print('in Child Classes') } }
// 使用 abstract 修飾符定義一個 抽象類—一個不能被實例化的類。 抽象類一般用來定義接口, 以及部分實現 abstract class Doer { // 定義一個抽象類 void doSomething(); } class EffectiveDoer extends Doer { void doSomething() { // 實現這個抽象類 } }
使用 extends 定義子類, supper 引用 超類
class Television { void turnOn() { _illuminateDisplay(); _activateIrSensor(); } void test() { print('Television') } } class SmartTelevision extends Television { void turnOn() { super.turnOn(); _bootNetworkInterface(); _initializeMemory(); _upgradeApps(); } // 使用@override 註解來 代表你的函數是想覆寫超類的一個函數 @override void test() { print('SmartTelevision') } }
// 使用 enum 關鍵字來定義枚舉類型 enum Color { red, green, blue } assert(Color.red.index == 0); assert(Color.green.index == 1); assert(Color.blue.index == 2);
何爲類變量和類函數? 即不需實例化該類,使用類名.便可使用的變量或函數
使用 static 關鍵字來實現類級別的變量和函數。
import 'dart:math'; class Point { num x; num y; Point(this.x, this.y); static num distanceBetween(Point a, Point b) { var dx = a.x - b.x; var dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } } main() { var a = new Point(2, 2); var b = new Point(4, 4); var distance = Point.distanceBetween(a, b); assert(distance < 2.9 && distance > 2.8); }
這個泛型對於前端開發人員來講是個新概念。若是你查看 List 類型的 API 文檔, 則能夠看到 實際的類型定義爲 List<E>。 這個 <…> 聲明 list 是一個 泛型 (或者 參數化) 類型。 一般狀況下,使用一個字母來表明類型參數, 例如 E, T, S, K, 和 V 等。
例如,若是你但願一個 list 只包含字符串對象,你能夠 定義爲 List<String>, 這樣你、 你的同事、以及所使用的工具 ( IDE 以及 檢查模式的 Dart VM )能夠幫助你檢查你的代碼是否把非字符串類型對象給放到 這個 list 中了。
另一個使用泛型的緣由是減小重複的代碼。 泛型能夠在多種類型之間定義同一個實現, 同時還能夠繼續使用檢查模式和靜態分析工具提供的代碼分析功能。
var names = new List<String>(); names.addAll(['Seth', 'Kathy', 'Lars']); // 錯誤 names.add(42); // 減小代碼量 // 對象緩存 abstract class ObjectCache { Object getByKey(String key); setByKey(String key, Object value); } // 緩存字符串 abstract class StringCache { String getByKey(String key); setByKey(String key, String value); } .... // 使用泛型後, 定義一個通用的實現 abstract class Cache<T> { T getByKey(String key); setByKey(String key, T value); } // T 是一個備用類型。這是一個類型佔位符, 在開發者調用該接口的時候會指定具體類型 // 泛型函數 T first<T>(List<T> ts) { // ...Do some initial work or error checking, then... T tmp ?= ts[0]; // ...Do some additional checking or processing... return tmp; }
Dart 有一些語言特性來支持 異步編程。 最多見的特性是 async 方法和 await 表達式。
Dart 庫中有不少返回 Future 或者 Stream 對象的方法。 這些方法是 異步的。
是否是很眼熟。 async, await 是咱們在寫JS中常常見到的呀。那在個人理解是:
dart中的Future和Stream對象就至關於JS中的Promise對象
async 方法和 await 表達式 使用的JS中的使用是同樣的。
以上這些純屬我的學習記錄,本人是一名前端開發,對JS比較熟悉,因此有些地方會套用些JS的語法來作說明
若有錯誤及不妥之處,歡迎評論留言指出。