iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 4
0
自我挑戰組

從零開始的Flutter世界系列 第 4

Day04 Dart 語言介紹(二) 資料型態、條件式、迴圈

在上一篇,我們介紹了一些資料的基本型態,今天我們來介紹一下Dart 有哪些內建的資料型態,我們可以在Dart 上直接用這些內建的資料型態,去新增我們的物件,而這些物件都能夠使用它型態的特定方法,即API (Application Programming Interface),可以理解成是別人已經寫好的方法,提供給我們,不需要了解方法的原理,會使用就好。

Dart 的內建的資料型態有數值型 (num)布林型 (bool)字串 (String)MapListRunesSymbols,有一些資料型態已在上一篇介紹過,下面我們來看看這些資料型態怎麼使用吧

內建的資料型態

數值型 (num)
  • 數值型有兩種型態,一種是整數,另一種是浮點數

    main(){
      num pi = 3; //pi 型態為num,值可為 int
      pi = 3.14; //pi 型態為num,值可為 double
      print("pi = $pi");  //印出 pi = 3.14
    }
    
List
  • 為集合資料型別,在其他常見的程式語言見作陣列 (array),而在Dart 中陣列就是List物件,所以一般稱為lists,用[ ]表示List的內容,可用明確的資料型態宣告,未宣告元素型別時Dart 會自行判斷

  • main() {
      var list = [1, 2, 3]; //由Dart 推斷為 List<int> 型態
      //list.add("4");  會報錯,Error: The argument type 'String' can't be assigned to the parameter type 'int'.
    
      //使用 List型態類別的方法
      print(list.length);// 印出3,共有三筆資料
    
      List list2 = [1, 2, 3]; //為指定 List型態時,推斷為dynamic
      list2.add("4"); //不會出錯
    
      List<int> list3 = [1, 2, 3]; //為明確的 List<int> 型態
      //list3.add("4");  會報錯,Error: The argument type 'String' can't be assigned to the parameter type 'int'.
    
      var list4 = List(3); //此方法為建立固定長度的List,不能移除或者增加
      list4[0] = 1;
      list4[1] = 2;
      list4[2] = 3;
      print(list4); //印出 [1, 2, 3]
    
      //常數的List,不能對值做改變
      var constantList = const [1, 2, 3];
      // constantList[1] = 1; // 會報錯
    }
    
  • 集合資料皆由位置索引(index) 0 開始數第一個資料,最後一個資料的index即為 集合資料總長度 -1

    main() {
      var list = [1, 2, 3];
      print("list[0] = ${list[0]}"); //印出 list[0] = 1
      print("list[1] = ${list[1]}"); //印出 list[1] = 2
      print("list[2] = ${list[2]}"); //印出 list[2] = 3
    }
    
    
  • 在Dart 2.3後,spread operator (...) 以及 null-aware spread operator (...?),可以插入另一個集合的資料

    main() {
      var list = [1, 2, 3];
      var list2 = [0, ...list];
      print(list2); //印出 [0, 1, 2, 3]
    
      var list3;
      var list4 = [0, ...?list3];
      print(list4); //印出 [0]
    }
    
Set
  • Dart 2.2 後新增,用{ }表示Set的內容,用於相同類型物件的集合,可於型別宣告後或{ }前以< >宣告元素型別,未宣告元素型別時Dart 會自行判斷

  • List不同,Set是無序的,因此於Set無法使用[index]取得或設定指定索引的值,同時因為沒有索引值區分,Set所有元素是唯一的,故無法重複加入同樣的值,新增重複的值會被省略

  • Set的語法跟Map很像 (Map等等會介紹),但Set是在Dart 2.2 後才新增,故若用未明確宣告資料型態來宣告{ }的話,Dart 會推斷型態為Map

void main() {
  var set1 = {1, 2, 3}; // 推斷為 Set<int>
  var set2 = {}; // 推斷為 Map<dynamic, dynamic>, 不是 SET
  var set3 = <int>{}; // 為 Set<int>
  
// 與List與Map相同,可使用.length方法取得元素個數
  print(set1.length); //印出 3
  
  set1.add(3); //新增重複的值,會被省略
  print(set1.length); //印出 3
}
Map
  • Map是使用key-value的方式來儲存的資料型態,key 和value 可以是任何型別的物件,其中 key 是唯一,不能重覆,但值可以重複

    main(){
      var gifts = {
      // Key:    Value
      'first': 'partridge',
      //'first': 'abcdefg',   //會報錯,key重複了
      'second': 'turtledoves',
      'fifth': 'golden rings'
    	}; //推斷型態為 Map<String, String>
    
      var gifts2 = Map(); //推斷型態為 Map<dynamic, dynamic>
    	gifts2['first'] = 'partridge'; // 新增新的一對 key-value
    	gifts2['second'] = 'turtledoves';
    	gifts2['fifth'] = 'golden rings';
    
      var gifts3 = {}; //推斷型態為 Map<dynamic, dynamic>
    	gifts3['first'] = 'partridge';
    	gifts3['second'] = 'turtledoves';
    	gifts3['fifth'] = 'golden rings';
    
      //gifts、gifts2、gifts3,這三個物件內容都一樣
    
      //常數的Map,不能對值做改變
      Map<int,String> constantMap = const {
      2: 'helium',
      10: 'neon',
      18: 'argon',
    	};
    
      // constantMap[2] = 'Helium'; 會報錯
    }
    
Runes
  • Runes是代表字串的UTF-32 code points,Unicode為每一個字元、標點符號、表情符號等都定義了一個唯一的數值,要在String顯示32-bit Unicode 的值,也就是說在書寫系統中,每一個字母,數字都有唯一的數值,而由於在Dart 字串是UTF-16 code units 字元序列,所以在字串表達32-bit Unicode值就需要新的語法,通常用\uXXXX的方式表示Unicode code point,這裡的XXXX是4個16進位制的數。

    void main() {
      Runes heart = '\u2665';
      Runes laugh = '\u{1f600}';
      print(String.fromCharCodes(heart) + ' ' + String.fromCharCodes(laugh)); //印出 ♥ ?
    
      String heart2 = '\u2665';
      String laugh2 = '\u{1f600}';
      print(heart2 + ' ' + laugh2); //印出 ♥ ?
    }
    
Symbols
  • 用來代表Dart 程式宣告的操作符或者識別符號,使用到的機率很小,但是此功能對於通過名字來引用識別符號的情況還是非常有用的,像是混淆後的程式碼,識別符號的名字被混淆了,但是Symbol的名字一樣不會改變

    void main() {
      //有兩種新建Symbol的方式:Symbol('name') 或 #name
      print(Symbol('a') == #a); // 印出 true, == 是相等的運算符號,後面會介紹
    
      var name = 'test';
      Symbol symbol = #name;
      print(symbol); //印出 Symbol("name")
      print(#name); //印出 Symbol("name")
    }
    

運算子 (Operators)

  1. 判斷式用,為true 或 false

  2. 指定運算子:=

  3. 算術運算子:+ (加),- (減),* (乘),/ (除),% (取餘數)

  4. 算術指派運算子:+=,-=,*=,/=,%=

    void main() {
      int x = 1;
      int y = 2;
    
      //x += y; 即 x = x + y
      print("x += y = ${x += y}"); //印出 x += y = 3
    }
    
    
  5. 比較運算子:

    < ( 小於 ),<= ( 小於等於 ),> ( 大於 ),>= ( 大於等於 ),== ( 等於 ),!= ( 不等於 )

  6. 邏輯運算子:

    && (且),|| (或),!(非),^(xor,相同及false)

    void main() {
      print(true ^ true); //印出false
      print(false ^ true); //印出true
      print(true ^ false); //印出true
      print(false ^ false); //印出false
    }
    
  7. 三元運算子:

    語法:

    條件 ? 符合 : 不符合

    void main() {
      int a = 11;
      int b = a > 9 ? 99 : 100;
      print(b); //印出 99
      int c = a > 12 ? 99 : 100; 
      print(c); //印出 100
    }
    
    
  8. 遞增運算子 ( ++ ) 與 遞減運算子 ( -- )

    1. i ++ 與 ++ i 即是 i = i + 1,i -- 與 i -- 即是 i = i -1 ;

    2. ++ (--) 在後面即是後置遞增 (減) 在運算後做,在前面即是前置遞增 (減) 在運算前先做

      想看詳細介紹的可以看此範例

      void main() {
      int x = 1, y = 1;
      bool ex1 = ++x > ++y;
      /*
       x = x + 1;   x = 1 + 1 -> 2
       y = y + 1;   y = 1 + 1 -> 2
       x > y;   2 > 2 -> false
       ex1為false
      */
      print(ex1); //印出 false
      
      // reset x跟y
      x = 1;
      y = 1;
      
      bool ex2 = ++x > y++;
      /*
       x = x + 1;   x = 1 + 1 -> 2
       x > y;   2 > 1 -> true
       y = y + 1;   y = 1 + 1 -> 2
       ex2為true
      */
      print(ex2); //印出 true
      
      // reset x跟y
      x = 1;
      y = 1;
      
      bool ex3 = x++ > ++y;
      /*
       y = y + 1;   y = 1 + 1 -> 2
       x > y;   1 > 2 -> false
       x = x + 1;   x = 1 + 1 -> 2
       ex3為false
      */
      print(ex3); //印出 false
      
      int a = 7;
      int b = ++a; //b=8
      
      int c = 7;
      int d = c--; //d=7
      }
      
      

條件式

  • if else

    void main() {
    
      /*
      if(布林1) {
      //若布林1為true即執行此區塊,執行完不會執行其他區塊
    	}else if(布林2){
      //若布林1為false以及布林2為true即執行此區塊,執行完不會執行其他區塊
    	}else{
      //若布林1以及布林2都不是true才執行此區塊
    	}	
      */
    
      //大括號可以被省略但只有if下方的第一行會被視為if裡面的內容
    	int a = 0;
    	if (false) a = 2; // a = 0
    	if (false)
      	a = 3; // 在判斷式區域內,故應該執行,但條件為false,a 還是 0
    		print(a); // 已不在判斷式區域內,故有執行,a = 4
    }
    
  • switch

    使用==比較intStringEnum(後面介紹)、或者編譯時常量,每個非空case語句都必須有一個break。不然就得使用continuethrowreturn,當沒有case可以匹配時,可以使用``default` 語句來匹配這種預設情況

    main(){
       int a = 11;
    
       switch (a) {
        case 2:
          print("2");
          break;
        case 11:
          print("A");
          break;
        case 22:
          print("B");
          break;
        default:
          print("else");
      }
      //印出 A
    
    
      var command = 'CLOSED';
    	switch (command) {
      case 'CLOSED': // 通過空case 語句
      case 'NOW_CLOSED':
        // CLOSED 和 NOW_CLOSED,都會執行
        print("NOW_CLOSED"); //印出 NOW_CLOSED
        break;
    	}
    
    }
    

迴圈

  • for(初始值 ; 判斷是否停止或繼續做的條件 ; 如何讓迴圈停止的規則){

    ​ 欲執行的步驟

    }

    void main() {
      for (int x = 0; x < 5; x++) {
        print("x = $x");
      }
    //印出
    //x = 0
    //x = 1
    //x = 2
    //x = 3
    //x = 4
    }
    
  • for each

    void main() {
    //使用foreach迴圈 list 和 Set都可以用這種方式
      List numbers = [1, 2, 3, 4, 5];
      numbers.forEach((number) => print(number));
      /* 印出
      1
    	2
    	3
    	4
    	5
      */
    }
    
  • for in

    void main() {
      //使用for in迴圈,一般List和Set都是用這種方式
      List numbers = [1, 2, 3, 4, 5];
      for (var number in numbers) {
        print(number);
      }
      /* 印出
      1
    	2
    	3
    	4
    	5
      */
    }
    
  • while

    while(判斷是否停止或繼續做的條件) {

    ​ 欲執行的步驟

    }

    void main() {
      int x = 0;
      while (x < 5) {
        print("x = ${x++}");
      }
      //印出
      //x = 0
      //x = 1
      //x = 2
      //x = 3
      //x = 4
    }
    
  • do while

    do{

    ​ 欲執行的步驟

    } while(判斷是否停止或繼續做的條件)

    void main() {
      int x = 6;
      do {
        print("x = ${x++}");
      } while (x < 5);
      //印出 x = 6
    }
    
  • brea continue

    void main() {
      for (int x = 0; x < 10; x++) {
        if (x == 2) {
          continue; // x = 2時,跳過這次
        } else if (x == 5) {
          break; // x = 5時,中斷
        }
        print("x = $x");
      }
      //印出
      //x = 0
      //x = 1
      //x = 3
      //x = 4
    }
    
  • Assert

    如果條件式結果不滿足需求,則可以使用assert語句打斷程式碼的執行,只有在debug模式才能使用,若

    assert錯誤,會執行失敗並拋出異常

總結

今天補充完了資料型態,也介紹了一些基本運用,已經有程式基礎的應該很好上手,第一次學的人,建議搭配 DartPad,多做練習


上一篇
Day03 Dart 語言介紹(一) 基本資料類型、變數、常數
下一篇
Day05 Dart 語言介紹(三) 類別、函式
系列文
從零開始的Flutter世界30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言