Dart基礎知識

Flutter筆記發表於2019-05-25

這一篇我們不講Flutter 的知識,來講一講Dart 的基礎知識。

先來看看維基百科上關於Dart 的簡介:

Dart(是一種適用於全球資訊網開放原始碼程式語言,由Google主導開發,於2011年10月公開。它的開發團隊由Google Chrome瀏覽器V8引擎團隊的領導者拉爾斯·巴克主持,目標在於成為下一代結構化Web開發語言。

類似JavaScript,Dart也是一種物件導向語言,但是它採用基於類程式設計。它只允許單一繼承,語法風格接近C語言

再開啟 Dart 官網:dart.dev,映入眼簾的是:

Dart基礎知識

emmmm….很明顯,現在知道 Dart 語言的人大部分都是因為 Flutter,這與它的目標成為下一代結構化Web開發語言好像有點偏差。(不過在Flutter 1.5 釋出的時候釋出了 Flutter for web)

不過無所謂,無論它最開始的目標是什麼,既然我們現在想要學習 Flutter ,那就要了解 Dart 這門開發語言。

話不多說,我們開始。

首先我們要知道,Dart是一個純面嚮物件語言,也就是說,在Dart中,一切皆物件。

Dart程式碼長什麼樣子

好像我們看到的 Dart 程式碼都是從 Flutter 裡看見的,一個括號套一個括號,一大堆的括號。

那麼標準的 Dart 程式碼是什麼樣的:

// 定義個方法。
printNumber(num aNumber) {
  print('The number is $aNumber.'); // 在控制檯列印內容。
}

// 這是程式執行的入口。
main() {
  var number = 42; // 定義並初始化一個變數。
  printNumber(number); // 呼叫一個方法。
}
複製程式碼

好像沒什麼不同的,只是有一個 num 好像有點不太一樣(因為我是搞Android的,所以上來就看到了這一個問題)。

那我們就從變數開始講起。

變數

宣告變數

在 Dart 中,我們宣告一個變數有兩種方法:

var _str = '';
int _num = 1;
複製程式碼

所有用下劃線開頭的 無論是方法 還是變數 都是私有的。

我們可以用var 來宣告一個變數,也可以指定變數的型別。

那麼我們什麼時候用什麼樣的方式來宣告變數呢?

可以通過Dart程式碼風格推薦裡來查詢到:

對於區域性變數,使用 var 而不是具體的型別來定義區域性變數。

對於私有成員變數,推薦使用指定變數的型別來宣告變數。

常量

在 Dart 中,我們宣告常量有兩種方法:

const String constString = "";
final String _finalString;
複製程式碼

一種是用 const,一種是用 final。

兩種有什麼區別?

const

const 是在編譯時期就必須賦值,而且 const 在類中的話,就必須定義為 static const.

final

final 講道理不能說是定義為常量,而應該叫做不能被修改的變數。

因為被 final 修飾的變數只能在類初始化時賦值一次。在編譯時我們看不到其值。

所有內建的變數型別

Dart 內建支援下面這些型別:

  • numbers
  • strings
  • booleans
  • lists (也被稱之為 arrays)
  • maps
  • runes (用於在字串中表示 Unicode 字元)
  • symbols

簡單說兩個

numbers

Dart 支援兩種數值型別 int double ,這兩種型別都是 num 的子類

也就是說只要你定義的是數值型別,就可以用 num 來接收。

strings

String 可以用雙引號或者單引號來宣告。

在字串中可以用表示式 ${},也可以用 + 號來拼接字串。

其他的就不說了,至於後兩個很大可能用不到。

方法

Dart 是一個真正的面嚮物件語言,方法也是物件並且具有一種型別, Function型別。

也就是說,我們可以把方法賦值成變數,來傳入另一個方法。

一個簡單的方法

來定義一個簡單的方法:

Widget build(BuildContext context) {
  return Container();
}
複製程式碼

就拿 Flutter 中的 build來說,這就是一個最基本的 Dart 方法。

返回型別為 Widget, 形參為 BuildContext。裡面只有一行程式碼 return Container();

那對於一個方法中只有一個表示式的,我們可以這麼寫:

Widget build(BuildContext context) => Container();
複製程式碼

這個 => Container(); 語法是 { return Container; } 形式的縮寫。=> 語法也稱為 胖箭頭 語法。

可選引數

方法可以有兩種型別的引數:必需的和可選的。 必需的引數在引數列表前面, 後面是可選引數。

在 Dart 中可選引數也有兩種,可選命名引數 和 可選位置引數

可選命名引數
String demo(String name, {int age}){
  String result = '我的名字叫$name';
  if(age != null){
    result += ',我今年$age歲了';
  }
  return result;
}
複製程式碼

這就是一個可選的命名引數,我們這樣呼叫:

demo('HaSaKi', age: 18);
複製程式碼
可選位置引數

我們把剛才的demo 方法改造一下:

String demo(String name, [int age]){
  String result = '我的名字叫$name';
  if(age != null){
    result += ',我今年$age歲了';
  }
  return result;
}
複製程式碼

把大括號改為了中括號,這樣就成為了可選位置引數的方法。

要這樣呼叫:

demo('HaSaKi', 18);

複製程式碼

引數預設值

在定義方法的時候,我們可以使用 = 來定義引數的預設值

預設值必須是編譯時常量。

舉個例子:

String demo(String name, {int age = 18}){
  String result = '我的名字叫$name';
  if(age != null){
    result += ',我今年$age歲了';
  }
  return result;
}

複製程式碼

這個方法現在就算不傳 age 的值,也永遠都會輸出,我今年18歲了。因為給了age預設值。

Dart 中的類和Java 類似,單繼承,並且 Object 是所有類的超類。

定義一個類:

class Person{
  String name;
  int age;
  
  say(){
    assert(name == null);
    print('我叫$name');
  }
}

複製程式碼

可以說和其他語言一樣了。

下面來點不一樣的。

簡化變數賦值

在其他語言中,我們經常會使用建構函式來給類變數賦值。

由於這種需求特別常見,所以 Dart 提供了一個語法糖:

class Person {
  String name;
  int age;
  
  Person(this.name, this.age);

  say() {
    assert(name == null);
    print('我叫$name');
  }
}

複製程式碼

命名建構函式

在 Dart 中,可以使用命名建構函式來更清晰的表達你的意圖:

class Person {
  String name;
  int age;

  Person.fromJson(Map json) {
    this.name = json['name'];
    this.age = json['age'];
  }

  say() {
    assert(name == null);
    print('我叫$name');
  }
}


複製程式碼

工廠構造方法

如果一個建構函式並不總是返回一個新的物件,則使用 factory 來定義這個建構函式。

單例也是我們經常使用的, 我們可以使用工廠構造方法來讓我們實現單例:

class Person {
  static final Person _person = Person._internal();

  factory Person() {
    return _person;
  }

  Person._internal();
}


複製程式碼

可以看到,我們定義了一個私有命名建構函式,也定義了一個工廠建構函式。

定義一個 final 的 Person 物件,然後用工廠建構函式返回它。

我們來測試一下:

print(Person() == Person());

flutter: true

複製程式碼

可以證明這樣寫是沒問題的。

級聯呼叫

我們平時為類的值賦值或呼叫方法的時候,是這麼寫的:

var person = Person();
person.name = '哈哈';
person.age = 18;
person.say();

複製程式碼

有沒有很麻煩?Dart 也為我們考慮到了:

Person()
  ..name = '哈哈'
  ..age = 18
  ..say();

複製程式碼

總結

目前就寫這麼多基礎的知識吧,可以看到 Dart 為我們開發人員考慮了很多,是個現代化語言該有的樣子。

而現在我們在Flutter 當中所看到的 Dart 程式碼只是冰山一角,後續我也會繼續為大家寫Dart 系列。

請持續關注。

Dart基礎知識