【自學flutter系列】dart語言學習概覽

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

內置類型

Numbers

  • int 整數
  • double 浮點數
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);

Strings

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.""";

Booleans(布爾值)

Dart 有一個名字爲 bool 的類型。 只有兩個對象是布爾類型的:true 和 false 所建立的對象, 這兩個對象也都是編譯時常量。數組

通俗地講就是dart判斷bool值就是隻能用true和false,像JS的0, 1, null等都能判斷表達式真假,dart不能。緩存

var name = 'Bob';
if (name) { // 這裏dart會拋出一個異常, 表示name變量不是一個布爾值。
    // javascript 能夠這樣判斷, dart 不能
    print('Bob');
}

Lists(列表)

至關於JS裏的數組,表示爲有序的集合。

Maps

至關於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

runes 表明字符串的 UTF-32 code points。

symbols

略過

Functions 函數 (方法)

在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...

  1. var a = 10;這種賦值語法的含義是a是指向一個內存對象10的引用(ref).
  2. var a = 10; var b=a; 則a,b都指向同一個內存對象,即引用同一個內存對象。可是a,b之間沒有任何聯繫。
  3. 在2的狀況下,修改a指向對象的值,b也會跟着改。(矛盾點也在這裏!)
  4. 可是,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 要確保某些代碼執行,無論有沒有出現異常都須要執行

Classes 類

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)

使用 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的語法來作說明

若有錯誤及不妥之處,歡迎評論留言指出。

上一篇: 【自學flutter系列】flutter 開發環境搭建

相關文章
相關標籤/搜索