• Github 中文镜像
Sign inSign up
Watch966
Star102.4k
Fork61.8k
Tag: dart
Switch branches/tags
Branches
Tags
K / Dart 语法速览(一).md
移动浏览 Clone
加载中...
到移动设备上浏览
351 lines 23.63 KB
First commit on 31 Oct 2020

    只适用于有编程基础的人

    • 这是第一篇:类型和声明。
    • 第二篇是控制语句、运算符、异常、函数、类。

    hello, world

    // main 标准写法
    void main() {
        // 注意: Dart和Java一样表达式以分号结尾,写习惯Kotlin的小伙伴需要注意了,
        // 这可能是你从Kotlin转Dart最大不适之一。
        print('Hello World!');
    }
    
    // dart中void类型,作为函数返回值类型可以省略
    main() {
        print('Hello World!');
    }
    
    // 如果函数内部只有一个表达式,可以省略大括号,使用"=>"箭头函数;
    // 而对于Kotlin则是如果只有一个表达式,可以省略大括号,使用"="连接,
    // 类似 fun main(args: Array<String>) = println('Hello World!')
    void main() => print('Hello World!');
    
    // 最简写形式
    main() => print('Hello World!');
    

    数据类型

    bool

    main() {
        // 注意,dart还是和Java类似的 [类型][变量名]方式声明,
        // 这个和Kotlin的 [变量名]:[类型]不一样.
        bool isClosed = true;
        bool isOpened = false;
    }
    

    数字:num、int、double

    dart 中没有 float, short, long。

    main() {
        print(3.141592653.toStringAsFixed(3)); //3.142 保留有效数字
        print(6.6.floor()); // 6向下取整
        print((-6.6).ceil()); //-6 向上取整
        print(9.9.ceil()); //10 向上取整
        print(666.6.round()); //667 四舍五入
        print((-666.6).abs()); // 666.6 取绝对值
        print(666.6.toInt()); //666 转化成int,这中toInt、toDouble和Kotlin类似
        print(999.isEven); //false 是否是偶数
        print(999.isOdd); //true 是否是奇数
        print(666.6.toString()); //666.6 转化成字符串
    }
    

    String

    单引号、双引号、三引号以及$字符串模板用法和Kotlin是一模一样的。

    main() {
        String name = 'Hello Dart!'; // 单引号
        String title = "'Hello Dart!'"; // 双引号
        String description = """
            Hello Dart! Hello Dart!
            Hello Dart!
            Hello Dart! Hello Dart!
        """; // 三引号
        num value = 2;
        String result = "The result is $value"; // 单值引用
        num width = 200;
        num height = 300;
        String square = "The square is ${width * height}"; // 表达式的值引用
    }
    
    main() {
        String url = "https://mrale.ph/dartvm/";
        print(url.split("://")[0]); //字符串分割split方法,类似Java和Kotlin
        print(url.substring(3, 9)); //字符串截取substring方法, 类似Java和Kotlin
        print(url.codeUnitAt(0)); //取当前索引位置字符的UTF-16码
        print(url.startsWith("https")); //当前字符串是否以指定字符开头, 类似Java和Kotlin
        print(url.endsWith("/")); //当前字符串是否以指定字符结尾, 类似Java和Kotlin
        print(url.toUpperCase()); //大写, 类似Java和Kotlin
        print(url.toLowerCase()); //小写, 类似Java和Kotlin
        print(url.indexOf("ph")); //获取指定字符的索引位置, 类似Java和Kotlin
        print(url.contains("http")); //字符串是否包含指定字符, 类似Java和Kotlin
        print(url.trim()); //去除字符串的首尾空格, 类似Java和Kotlin
        print(url.length); //获取字符串长度
        print(url.replaceFirst("t", "A")); //替换第一次出现t字符位置的字符
        print(url.replaceAll("m", "M")); //全部替换, 类似Java和Kotlin
    }
    

    类型检查(is和is!)和强制类型转换(as)

    和 Kotlin 一样,dart 也是通过 is 关键字来对类型进行检查以及使用 as 关键字对类型进行强制转换,如果判断不是某个类型 dart 中使用 is! , 而在 Kotlin 中正好相反则用 !is 表示。

    main() {
        int number = 100;
        double distance = 200.5;
        num age = 18;
        print(number is num); // true
        print(distance is! int); // true
        print(age as int); // 18
    }
    

    Runes 和 Symbols 类型

    Runes类型是UTF-32字节单元定义的Unicode字符串,Unicode可以使用数字表示字母、数字和符号,然而在dart中String是一系列的UTF-16的字节单元,所以想要表示32位的Unicode的值,就需要用到Runes类型。

    我们一般使用 \uxxxx 这种形式来表示一个Unicode码,xxxx 表示4个十六进制值。当十六进制数据多余或者少于4位时,将十六进制数放入到花括号中,例如,微笑表情( )是 \u{1f600}

    而Symbols类型则用得很少,一般用于Dart中的反射,但是注意在Flutter中禁止使用反射。

    main() {
        var clapping = '\u{1f44f}';
        print(clapping);
        print(clapping.codeUnits); // 返回十六位的字符单元数组
        print(clapping.runes.toList());
    
        Runes input = new Runes(
            '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
        print(new String.fromCharCodes(input));
    }
    

    Object 类型

    在Dart中所有东西都是对象,都继承于Object, 所以可以使用Object可以定义任何的变量,而且赋值后,类型也可以更改。

    main() {
        Object color = 'black';
        color = 0xff000000; // 运行正常,0xff000000类型是int, int也继承于Object
    }
    

    dynamic 类型

    var 声明的变量未赋值的时候就是dynamic类型, 它可以像Object一样可以改变类型。dynamic类型一般用于无法确定具体类型, 注意: 建议不要滥用dynamic,一般尽量使用Object, 如果你对Flutter和Native原生通信PlatformChannel代码熟悉的话,你会发现里面大量使用了dynamic,因为可能native数据类型无法对应dart中的数据类型,此时dart接收一般就会使用dynamic。

    Object和dynamic区别在于: Object会在编译阶段检查类型,而dynamic不会在编译阶段检查类型。

    main() {
        dynamic color = 'black';
        color = 0xff000000; // 运行正常,0xff000000类型是int, int也继承于Object
    }
    

    变量和常量

    var 关键字

    在dart中可以使用var来替代具体类型的声明,会自动推导变量的类型,这是因为var并不是直接存储值,而是存储值的对象引用,所以var可以声明任何变量。

    在Flutter开发一般会经常使用var声明变量,以便于可以自动推导变量的类型。

    main() {
      int colorValue = 0xff000000;
      var colorKey = 'black'; //var声明变量 自动根据赋值的类型,推导为String类型
      // 使用var声明集合变量
      var colorList = ['red', 'yellow', 'blue', 'green'];
      var colorSet = {'red', 'yellow', 'blue', 'green'};
      var colorMap = {'white': 0xffffffff, 'black': 0xff000000};
    }
    

    需要注意的是:如果var声明的变量开始不初始化,不仅值可以改变,它的类型也是可以被修改的,但是一旦开始初始化赋值后,它的类型就确定了,后续不能被改变。

    main() {
      var color; // 仅有声明未赋值的时候,这里的color的类型是dynamic,所以它的类型是可以变的
      color = 'red';
      print(color is String); //true
      color = 0xffff0000;
      print(color is int); //true
    
      //声明时并赋值,这里colorValue类型已经推导出为int,并且确定了类型
      var colorValue = 0xffff0000;
      colorValue = 'red'; //错误,这里会抛出编译异常,String类型的值不能赋值给int类型
      print(colorValue is int); //true
    }
    

    常量(final和const)

    在dart中声明常量可以使用 constfinal 两个关键字,这两者的区别在于如果常量是编译期就能初始化的就用 const(有点类似 Kotlin 中的 const val)如果常量是运行时期初始化的就用 final (有点类似 Kotlin 中的 val)。

    main() {
        const PI = 3.141592653; // const定义常量
        final nowTime = DateTime.now(); // final定义常量
    }
    

    集合(List、Set、Map)

    List

    类似数组。

    1. 初始化

      main() {
          // 直接使用 [] 形式初始化
          List<String> colorList = ['red', 'yellow', 'blue', 'green'];
          var colorList = <String> ['red', 'yellow', 'blue', 'green'];
      
    2. 常用函数

          main() {
              List<String> colorList = ['red', 'yellow', 'blue', 'green'];
              colorList.add('white'); // 和Kotlin类似通过add添加一个新的元素
              print(colorList[2]); // 可以类似Kotlin一样,直接使用数组下标形式访问元素
              print(colorList.length); // 获取集合的长度,这个Kotlin不一样,Kotlin中使用的是size
              colorList.insert(1, 'black'); // 在集合指定index位置插入指定的元素
              colorList.removeAt(2); // 移除集合指定的index=2的元素,第3个元素
              colorList.clear(); // 清除所有元素
              print(colorList.sublist(1,3)); // 截取子集合
              print(colorList.getRange(1, 3)); // 获取集合中某个范围元素
      
              //类似Kotlin中的joinToString方法,输出: red<--->yellow<--->blue<--->green
              print(colorList.join('<--->'));
              print(colorList.isEmpty);
              print(colorList.contains('green'));
          }
      }
      
    3. 遍历

      main() {
          List<String> colorList = ['red', 'yellow', 'blue', 'green']; // for-i遍历
          for(var i = 0; i < colorList.length; i++) {//可以使用var或int
              print(colorList[i]);
          }
          //forEach遍历,参数为 Function。(使用了箭头函数)
          colorList.forEach((color) => print(color));
          //for-in遍历
          for(var color in colorList) {
              print(color);
          }
          //while+iterator迭代器遍历,类似Java中的iteator
          while(colorList.iterator.moveNext()) {
              print(colorList.iterator.current);
          }
      }
      

    Set

    Set 中的元素是不能重复的。所以添加重复的元素时会返回 false,表示添加不成功。

    1. 初始化

      main() {
          // 直接使用 {} 形式初始化
          Set<String> colorSet= {'red', 'yellow', 'blue', 'green'};
          var colorList = <String> {'red', 'yellow', 'blue', 'green'};
      }
      
    2. Set 中的交、并、补集

      main() {
          var colorSet1 = {'red', 'yellow', 'blue', 'green'};
          var colorSet2 = {'black', 'yellow', 'blue', 'green', 'white'};
      
          //交集-->输出: {'yellow', 'blue', 'green'}
          print(colorSet1.intersection(colorSet2));
      
          //并集--->输出: {'black', 'red', 'yellow', 'blue', 'green', 'white'}
          print(colorSet1.union(colorSet2));
      
          //补集--->输出: {'red'}
          print(colorSet1.difference(colorSet2));
      }
      
    3. 遍历

      和 List 一样。

    Map

    字典,Key: Value 存储,key 是不能重复的。

    1. 初始化

      main() {
          // 使用 {key:value} 形式初始化
          Map<String, int> colorMap = {'white': 0xffffffff, 'black':0xff000000};
          var colorMap = <String, int>{'white': 0xffffffff, 'black':0xff000000};
      }
      
    2. Map 常用函数

      main() {
          Map<String, int> colorMap = {'white': 0xffffffff, 'black':0xff000000};
          print(colorMap.containsKey('green')); // false
          print(colorMap.containsValue(0xff000000)); // true
          print(colorMap.keys.toList()); // ['white','black']
          print(colorMap.values.toList()); // [0xffffffff, 0xff000000]
          colorMap['white'] = 0xfffff000; // 修改指定key的元素
          colorMap.remove('black'); // 移除指定key的元素
      }
      
    3. Map 遍历

      main() {
          Map<String, int> colorMap = {'white': 0xffffffff, 'black':0xff000000};
          //for-each key-value
          colorMap.forEach((key, value) => print('color is $key, color value is $value'));
      }
      
    4. Map.fromIterables 将 List 转化成 Map

      main() {
          List<String> colorKeys = ['white', 'black'];
          List<int> colorValues = [0xffffffff, 0xff000000];
          Map<String, int> colorMap = Map.fromIterables(colorKeys, colorValues);
      }
      

    集合常用的操作符

    main() {
        List<String> colorList = ['red', 'yellow', 'blue', 'green'];
        // forEach 箭头函数遍历,如果箭头函数内部只有一个表达式可以省略大括号
        colorList.forEach((color) => { print(color) });
    
        // map 函数的使用
        print(colorList.map((color) => '$color_font').join(","));
    
        // every 函数的使用,判断里面的元素是否都满足条件,返回值为 true/false
        print(colorList.every((color) => color == 'red'));
    
        // sort 函数的使用
        List<int> numbers = [0, 3, 1, 2, 7, 12, 2, 4];
        numbers.sort((num1, num2) => num1 - num2); //升序排序
        numbers.sort((num1, num2) => num2 - num1); //降序排序
        print(numbers);
    
        // where 函数使用,相当于Kotlin中的filter操作符,返回符合条件元素的集合
        print(numbers.where((num) => num > 6));
    
        // firstWhere 函数的使用,相当于Kotlin中的find操作符,
        // 返回符合条件的第一个元素,如果没找到返回 null。
        // 注意: 如果没有找到,执行 orElse 代码块,可返回一个指定的默认值
        print(numbers.firstWhere((num) => num == 5, orElse: () => -1));
    
        // singleWhere 函数的使用,返回符合条件的第一个元素,如果没找到返回 null,
        // 但是前提是集合中只有一个符合条件的元素, 否则就会抛出异常
        // 注意: 如果没有找到,执行orElse代码块,可返回一个指定的默认值
        print(numbers.singleWhere((num) => num == 4, orElse: () => -1));
    
        // take(n)、skip(n) 函数的使用,take(n)表示取当前集合前n个元素,
        // skip(n)表示跳过前n个元素,然后取剩余所有的元素。
        print(numbers.take(5).skip(2));
    
        // List.from 函数的使用,从给定集合中创建一个新的集合,相当于 clone 一个集合。
        print(List.from(numbers));
    
        // expand 函数的使用,将集合一个元素扩展成多个元素或者将多个元素
        // 组成二维数组展开成平铺一个一位数组
        var pair = [
            [1, 2],
            [3, 4]
        ];
        print('flatten list: ${pair.expand((pair) => pair)}');
    
        var inputs = [1, 2, 3];
        print('duplicated list: ${inputs.expand((number) =>[
            number,
            number,
            number
        ])}');
    }
    

    下一篇:Dart 语法速览(二)


    参考资料: