Flutter (一) Dart 語言基礎詳解(變數、內建型別、函式、操作符、流程控制語句)

DevYK發表於2019-03-20

變數

變數的宣告

  1. var
  2. dynamic
  3. Object
  • 宣告一個未初始化的變數,變數的型別可以更改

    //變數
    /// 三斜槓文件註釋
    /// 返回型別 void 可以省略,省略後的返回值為 null
    
    void main(){
      ///----------------------- 變數的宣告-----------------
      ///宣告一個未初始化的變數,變數的型別可改變
      var data;
      data = "HelloWorld";
    
      dynamic data1;
      data1 = "HelloWorld1";
      data1 = 123;
    
      Object data2;
      data2 = 'HelloWorld2';
      data2 = 123;
      print([data,data1,data2]);
    }
    
    /// 列印效果
    lib/1-variables.dart:1: Warning: Interpreting this as package URI, 'package:flutter_test3/1-variables.dart'.
    [HelloWorld, 123, 123]
    
    複製程式碼
  • 宣告一個初始化的變數,變數型別不能再更改

     var variablel =
          'HelloWorld'; //變數是一個引用,名字為 variablel 的變數引用了一個內容為‘HelloWorld’的 String 物件。
    //  variablel = 123; //變數初始化後,variablel 變數的型別被推斷為String型別,其型別不能再改變
    複製程式碼
  • dynamic 和 Object 宣告的變數初始化後,變數的型別仍可改變

    dynamic variable2 = "HelloWorld";
      variable2 = 123;
    //  variable2.test();//呼叫不存在的test()方法,編譯通過,執行報異常。編譯階段不檢查型別
    
      Object variable3 = 'HelloWorld';
      variable3 = 123;
    //  variable3.test();//呼叫不存在的test()方法,編譯不通過。編譯階段檢查型別
    複製程式碼
  • 使用確定型別顯示宣告變數,變數的型別不能再改變

    String name3 = "HelloWorld";
    //  name3 =123; //變數的型別不能更改
    複製程式碼

變數宣告總結

  1. var: 如果沒有初始值,可以變成任何型別

  2. dynamic:動態任意型別,編譯階段不檢查型別

  3. Object 動態任意型別,編譯階段檢查型別

    區別:

    1. 唯一區別 var 如果有初始值,型別被是鎖定

預設值

  • 沒有初始化的變數預設值都是null

    一切皆物件,物件的預設值是null

    bool isEmpty;
    print((isEmpty == null));
    複製程式碼

final 和 const

  • 被 final 或者 const 修飾的變數,變數型別可以省略

     final FVariablel = "HelloWorld";
    //  final  String FVariablel = "HelloWorld";
    
      const cVariablel = "HelloWorld";
    //  const String cVariablel = "HelloWorld";
    複製程式碼
  • 被 final 或 const 修飾的變數無法再去修改其值。

    //   fVariable1 = '123';
    //   cVariable1 = '123456';
    複製程式碼
  • 如果是類級別常量,使用 static, const 。

    DateTime; //可參照DateTime static const int monday = 1;
    複製程式碼
  • const 可以使用其他 const 常量的值來初始化其值.

    const width = 100;
    const height = 100;
    const square = width * height;
    複製程式碼
  • const 賦值申明可省略

    const List clist = [1, 2, 3];
    //  const List clist = const [1, 2, 3];//dart 2之前,const賦值必須用const宣告
    print("\n\n\n");
    print(clist);
    複製程式碼
  • 可以更改非 final,非 const 變數的值,即使它曾經具有 const 值

    var varList = const [1, 2, 3];
      final finalList = const [1, 2, 3];
      const constList = [1, 2, 3];
      print([varList, finalList, constList]);
      varList = [1];
    //  constList[1];
    //  finalList[1];
      print("\n\n");
      print([varList, finalList, constList]);
    
    	列印效果--
      /***
       * [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
       * [[1], [1, 2, 3], [1, 2, 3]]
       */
    
    複製程式碼
  • const 導致的不可變性是可傳遞的

    final List ls = [1, 2, 3];
      ls[2] = 444;
      print(ls);
      const List cLs = [4, 5, 6];
    //  cLs[1] = 4;
      print("\n");
      print(ls);
    
    報錯:
          /***
       * Unhandled exception:
          Unsupported operation: Cannot modify an unmodifiable list
          #0      UnmodifiableListBase.[]= (dart:_internal/list.dart:90:5)
          #1      main (package:flutter_test3/1-variables.dart:103:6)
       */
    複製程式碼
  • 相同的 const 常量不會在記憶體中重複建立

    final finalList1 = [1, 2, 3];
    final finalList2 = [4, 5, 6];
    print("\n");
    print(identical(finalList1, finalList2)); //identical用於檢查兩個引用是否指向同一個物件
    
    const constList1 = [1, 2];
    const constList2 = [1, 2];
    print("\n");
    print(identical(constList1, constList2)); //identical用於檢查兩個引用是否指向同一個物件
    複製程式碼
  • const 需要是編譯時常量

    final DateTime finalDateTime = DateTime.now();
    //    const DateTime constDateTime = DateTime.now();//DateTime.now() 是執行期計算出來的值
      const sum = 1 + 2; //使用內建資料型別的字面量通過基本運算得到的值
      const aConstNum = 0;
      const aConstBool = true;
      const aConstString = 'a constant string';
      const aConstNull = null;
      const validConstString =
          '$aConstNum, $aConstBool, $aConstString, $aConstNull';
      print(validConstString); //使用計算結果為null或數字,字串或布林值的編譯時常量的插值表示式
    複製程式碼

final 和 const 總結

共同點

  • 宣告的型別可省略
  • 初始化後不能再賦值
  • 不能和 var 同時使用

區別(需要注意的地方)

  • 類級別常量,使用 static ,const 。
  • const 可使用其他 const 常量的值來初始化其值
  • const 可使用其他 const 常量的值來初始化其值
  • 可以更改非 final、非 const 變數的值,即使曾經具有 const 值
  • const 導致的不可變性是可傳遞的
  • 相同的 const 常量不會在記憶體中重複建立
  • const 需要是編譯時常量

內建型別

Number 數值(num,int,double)

int i = 1; //整數型
double d = 1.0 ;//double b4-bit(雙精度)浮點數
int bitLength = i.bitLength;
print('bitLength:${bitLength}'); //bitLength 判斷 int 值需要多少位 bit 位。
double maxFinite = double.maxFinite;
print('maxFinite: ${maxFinite}'); //maxFinitedouble的最大值
//int和double都是num的子類
num n1 = 1;
num n2 = 1.0;
//支援 十進位制、十六進位制
int il = oxfff;
//科學計數法
double dl = 1.2e2; //120.0
//轉換
//String > int
int i2 = int.pasrse('1');
double d2 = 1;//當 double 的值為 int 值時,int 自動轉為 double
print('d2:${d2}');
int i2 = int.try.parse('1.0');//返回 null

//int > String
int is = 123;
String s = 123.toString;

複製程式碼

String 字串

//Dart 字串是 UTF-16 編碼的字元序列,可以使用單引號或者雙引號來建立字串
var name = 'HelloWorld';
//可以在字串中使用表示式: ${expression},如果表示式是一個識別符號,可以省略 {}。 如果表示式的結果為一個物件,則 Dart 會呼叫物件的 toString() 函式來獲取一個字串
var names = 'HelloWorld ${name}';
//r 字首可以建立一個 “原始 raw” 字串
var rawNames = r"HelloWorld ${name}";
print('name:${names}');
print('rawNames :${rawNames}');
//如果表示式的結果為一個物件,則 Dart 會呼叫物件的 toString() 函式來獲取一個字串。
pint(Map);
//可以使用三個單引號或者雙引號也可以 建立多行字串物件
var multiLinesString = '''
Java Android
Flutter''';
pint('mutiLinesString:${mutiLinesString}');

/// StringBuffer
var sb = StringBuffer(); //dart 2 可以省略 new
sb..write('aaa')..write('bbb')..write('ccc');//..級聯符實現鏈式呼叫
sb.writeAll([aaa,bbb,ccc],',');//第二個參數列示分隔符,將第一個引數列表裡的資料用這個分隔符拼接起來
pint('sb:${sb}');

複製程式碼

Booleans 布林值 (bool)

//bool :true 和 false
bool isNull;
print('isNull: ${isNull}');
複製程式碼

List 列表(陣列 List)

//宣告一個自動長度的陣列
List growableList = new List();
//List growbleList = new List()..length = 3;
growbleList..add(1)..add(2)..add('HelloWorld');
pint('growbleList: ${growbleList}');

//宣告一個固定長度的陣列
var list = List(6);// 這裡可以用 var 宣告,也可以用 List
list[0] = "Java";
list[1] = "Android";
list[2] = "Dart";
list[3] = "Flutter";
list[4] = "C++";
list[5] = "C"
pint('list:${list}');

//元素固定型別
var typeList = List<String>;
typeList..add("1")..add("2")..add("3");
pint('typeList:${typeList}');

//常用屬性-獲取第一個元素
String first = typeList.fisrt;
pint('typeList.fisrt:$typeFirst');
//最後一個元素
String last = typeList.last;
pint('typeList.last:${last}');
//元素個數
int typeListLength = typeList.length;
pint('typeListLength:${typeListLength}');
//元素是否為空
bool isEmpty = typeList.isEmpty;
pint('typeList.isEmpty:${isEmpty}');
//元素是否不為空
bool isNotEmpty = typeList.isNotEmpty;
pint('typeList.isNotEmpty:${isNotEmpty}');
//陣列倒序
Iterable reversed = typeList.reversed;
print('typeList.reversed:${reversed}');

// 常用方法 增刪改查,排序,洗牌,複製子列表
var list4 = [];
//增
list4.add(1);
pint('add 1:${list4}');
list4.addAll([2,3,4]);
print('addAll[2,3,4]:${list4}');
list4.insert(0,0);
print('insert(0,0) : ${list4}');
list4.insertAll(1,[5,6,7,8]);
print('insertAll(1,[5,6,7,8]) :${list4}');
//刪除
list4.remove(5);
print('remove 5 :${list4}');
list4.removeAt(2);
print('remove at 0:${list4}');
//改
list4[4] = 5;
print('updata list4[4] to 5 :${list4}');
//range
list4.fillRange(0,3,9);
print('fillRange updata list4[0] - list[2] to 9 :$list4');
Iterable getRange = list4.getRange(0,3);
print('getRange list4[0]-list[2]:${getRange}');
//查
var contains = list.contains(5);
print('contains 5 :${contains}');
var indexOf = list4.indexOf(1);
print('list4 indexOf 1 :${indexOf}');
int indexWhere = list4.indexWhere((test) => test == 5);
print('list4 indexWhere 5 :${indexWhere}');
// 排序
list4.sort();
print('list4 sort:${list4}');
//洗牌
list4.shuffle();
print('list4 shuffle:${list4}');
//複製子列表
var list5 = list4.shulist(1);
print('sublist(1) list5: ${list5}');
//操作符
var list6 =[8,9];
print('list6:${list6}');
var list7 = list5 + list7;
print('list5 + list6:${list7}');

複製程式碼

Maps 鍵值對集合 (Map)

//宣告一個動態型別的 Map
var dynamicMap = Map();
dynamicMap['name'] = 'HelloWorld';
dynamicMap[1] = 'android';
print('dynamicMap :${dymaicMap}');
//強型別
var map = Map<int,String>();
map[1] = 'java';
map[2] = 'Android';
print('map :${map}');
//也可以這樣宣告
var map1 = {'name':'Java',1:'android'};
map1.addAll({'name','Flutter'});
print('map1:${map1}');
  //常用屬性
//  print(map.isEmpty); //是否為空
//  print(map.isNotEmpty); //是否不為空
//  print(map.length); //鍵值對個數
//  print(map.keys); //key 集合
//  print(map.values); //value集合    
複製程式碼

Set 集合 (Set)

// Set 無重複列表
var dynamicSet = Set();
dynamicSet.add('java');
dynamicSet.add('Android');
dynamicSet.add('Flutter');
dynamicSet.add('C/C++');
dynamicSet.add('1');
dynamicSet.add('1');
print('dynamicSet :${dynamicSet}');

//常用屬性與 List 類似
//常用方法 增刪改查與 List 類似
var set1 = {'java','Android'};
print('set1: ${set1}');
var differencel2 = set1.difference(set2);
var difference21 = set1.difference(set1);
print('set1 difference set2 :${differencel2}');//返回 set1 集合裡有但 set2 裡沒有的元素集合
print('set2 difference set1 :${difference2l}');//返回 set2 集合裡面有但 set1 裡沒有的元素集合
var intersection = set1.intersection(set2);
print('set1 set2 交集 :${intersection}');//返回 set1 和 set2 的交集
var union = set1.union(set2);
print('set2 set1並集:${union}');
set2.retainAll(['java','Android']);//只保留(要保留的元素要在原 set 中存在)
print('set2 只保留 java Android :${set2}');
複製程式碼

Runes 符號字元

//Runes用於在字串中表示Unicode字元 //https://copychar.cc/emoji/
String runesStr = '?';
print(runesStr);
print(runesStr.length); //表示佔 2 個 16 位字元
print(runesStr.runes.length); //表示佔 1 個 32 位字元

Runes runes = new Runes('\u{1f605} \u6211');
var str1 = String.fromCharCodes(runes); //使用String.fromCharCodes顯示字元圖形
print(str1);
String str2 = '\u{1f605} \u6211'; //如果非4個數值,需要把編碼值放到大括號中
print(str2)

複製程式碼

Symbols 識別符號

//Symbol識別符號 主要是反射用,現在mirrors已經被移除了
複製程式碼

函式

定義

  • 可在函式內定義

    void main(){
        int add(int x,int y){
            return x + y;
        }
        
        print(add(1,2));
    }
    複製程式碼
  • 定義函式時可省略型別

    void main(){
        add( x, y){ //不建議省略
            return x + y;
        }
        print(add(3,4));
    }
    複製程式碼
  • 支援縮寫語法 =>

    void main(){
        int add2(int x,int y) => x + y;
        /// 等同於
        int add3(int x,int y){
            return x + y;
        }
         print(add2(3,4));
         print(add3(3,4));
    }
    複製程式碼

可選引數

  • 可選命名引數,使用 {param1,param2,...} 的形式來指定命名引數

    void main(){
        int add3({int x,int y,int z}){
            x ?? = 1;
            x ?? = 2;
            x ?? = 3;
            return x + y + z;
        }
        print(add3());
    }
    複製程式碼
  • 可選位置引數,把可選引數放在 [ ] 中,必填引數要放在可循引數前面

    void main(){
        int add(int x,[int y ,int z]){
            y ?? = 2;
            z ?? = 3;
            return x + y + z;
        }   
        print(add(1));
    }
    複製程式碼
  • 可選命名引數預設值(預設值必須是編譯時常量),目前可使用等號 ‘=’ 或 ‘:’,Dart SDK 1.21 之前只能用冒號,冒號的支援以後會移除,所以建議使用等號

    void main(){
        int add5(int x,[int y =2,int z = 3]){
            return x + y +z;
        }
        //前面的必填引數沒有名字
        print(add(5,y:10,z:20));
    }
    
    //可選位置引數預設值(預設值必須是編譯時常量),只能使用等號 “=”
    void mian (){
        int add6(int x,[int y = 2,int z = 3]){
            return x + y + z;
        }
        
        print(add6(1));
    }
    
    //使用 list 或者 map 作為預設值,但必須是 const
    void func({List list = const [1,2,3],Map map = const {1:1,'fun' :'全棧'}}){
        //TODO ----
    }
    複製程式碼

匿名函式

  • 可賦值給變數,通過變數呼叫

    //無參匿名函式
    var anonFunc1 = () => print('無參匿名函式');
    anonFunction();
    
    //有參匿名函式
    var anonFunc = (name) => 'I am ${name}';
    print(anonFunc('DevYK'));
    
    //通過()呼叫,不推薦
    (() => print('不推薦'))();
        
    複製程式碼
  • 可在其他函式中直接呼叫或傳遞給其他函式

    void main(){
        List test(List list,String func(str)){
            for(var i =0;i < list.length;i++){
                list[i] = func(list[i]);
            }
            return list;
        }
        
        var list = ['a','b','c','d','e'];
        print(test(list,(str) => str * 2)); // String * int ,Dart 和 Py 可以這樣用。
    
    
      //List.forEach()就用的匿名函式
      List list1 = [11, 12, 13];
      list1.forEach((item) => print('$item'));
    }
    
    複製程式碼

閉包

  • 返回 Function 物件(閉包)

    void main(){
        Function makeAddFunc(int x){
            x++;
            return (int y) => x + y;
        }
        var addFunc = makeAddFunc(2);
        print(addFunc(3));
    }
    複製程式碼

函式別名

  • 可以指向任何同簽名的函式

    void main(){
        MyFunc myFunc;
        myFunc = subtsract;
        myFunc(4,2);
        myFunc = divide;
        myFunc(4,2);
        //typeDef 作為引數傳遞給引數
        calculator(4,2,subtsract);
    }
    
    //函式別名
    typedef MyFunc(int a,int b);
    //根據 MyFunc 相同的函式簽名定義兩個函式
    subtsract(int a,int b){
        print('subtsract: ${a-b}');
    }
    divide(int a,int b){
        print('divide: ${a / b}');
    }
    //typedef 也可以作為引數傳遞給函式
    calculator(int a,int b,MyFunc func){
        func(a,b);
    }
    複製程式碼

操作符

字尾操作

  • 條件成員訪問 和 . 類似,但是左邊的操作物件不能為 null,例如 foo?.bar 如果 foo 為 null 則返回 null,否則返回 bar 成員。

    String a;
    print(a?.length);
    複製程式碼

取商操作符

  • 被除數 ÷ 除數 = 商 ... 餘數,A ~/ B = C,這個C就是商。相當於Java裡的 /

    print(2 / 3);
    print(2 ~/ 3);
    複製程式碼

型別判定操作符

  • as、is、is! 在執行時判定物件型別

    void main(){
        //as 型別轉換
    num iNum = 1;
    num dNum = 1.0;
    int i = iNum as int;
    double d = dNum as double;
    print([i,d]);
    
    // is 如果物件是指定的型別返回 true
    print(iNum is int);
    Child child;
    Child childl = new Child();
    print(child is Parent);//child is Null
    print(childl is Parent);
    
    // is! 如果物件是制定的型別返回 False
    print(iNum is! int);
    }
    class Parent {}
    class Child extends Parent {}
    
    複製程式碼

條件表示式

  • 三目運算子 condition ? expr1 : expr2

    bool isFinish = true;
    String textVal = isFinish ?'yes':'no';
    // expr1 ?? expr2,如果 expr1 是 non-null,返回其值; 否則執行 expr2 並返回其結果。
    bool isPaused;
    isPaused = isPaused ?? false;
    //或者
    isPaused ??= false;
    複製程式碼

級聯操作符

  • .. 可以在同一個物件上 連續呼叫多個函式以及訪問成員變數。 嚴格來說, 兩個點的級聯語法不是一個操作符。 只是一個 Dart 特殊語法。

    StringBuffer sb = new StringBuffer();
     sb
      ..write('Java')
      ..write('Android')
      ..write('\n')
      ..writeln('DevYK');
    複製程式碼

流程控制語句

if else

for , forEach , for-in

  • forEach

    collection.forEach(item) => print('forEach: ${item}');
    複製程式碼
  • for-in

      for (var item in collection) {
        print('for-in: $item');
      }
    複製程式碼

while , do 、while

break,continue

whitch case

相關文章