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

    只适用于有编程基础的人

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

    流程控制

    循环

    // for
    main() {
        List<String> colorList = ['red', 'yellow', 'blue', 'green'];
        for (var i = 0; i < colorList.length; i++) { // 可以用var或int
            print(colorList[i]);
        }
    }
    
    // while
    main() {
        List<String> colorList = ['red', 'yellow', 'blue', 'green'];
        var index = 0;
        while (index < colorList.length) {
            print(colorList[index++]);
        }
    }
    
    // do-while
    main() {
        List<String> colorList = ['red', 'yellow', 'blue', 'green'];
        var index = 0;
        do {
            print(colorList[index++]);
        } while (index < colorList.length);
    }
    
    // break and continue
    main() {
        List<String> colorList = ['red', 'yellow', 'blue', 'green'];
        for (var i = 0; i < colorList.length; i++) { // 可以用var或int
            if(colorList[i] == 'yellow') {
                continue;
            }
            if(colorList[i] == 'blue') {
                break;
            }
            print(colorList[i]);
        }
    

    条件判断

    // if-else
    void main() {
        var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
        for (var i = 0; i < numbers.length; i++) {
            if (numbers[i].isEven) {
                print('偶数: ${numbers[i]}');
            } else if (numbers[i].isOdd) {
                print('奇数: ${numbers[i]}');
            } else {
                print('非法数字');
            }
        }
    }
    
    // 三目运算符(? : )
    void main() {
      var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
      for (var i = 0; i < numbers.length; i++) {
          num targetNumber = numbers[i].isEven ? numbers[i] * 2 : numbers[i] + 4;
          print(targetNumber);
      }
    }
    
    // switch-case
    Color getColor(String colorName) {
      Color currentColor = Colors.blue;
      switch (colorName) {
        case "read":
            currentColor = Colors.red;
            break;
        case "blue":
            currentColor = Colors.blue;
            break;
        case "yellow":
            currentColor = Colors.yellow;
            break;
      }
      return currentColor;
    }
    
    

    Assert(断言)

    断言只在检查模式下运行有效,如果在生产模式运行,则断言不会执行。

    assert(text != null); // text为null,就会中断后续代码执行
    assert(urlString.startsWith('https'));
    

    运算符

    算数运算符

    名称运算符例子
    +var result = 1 + 1;
    -var result = 5 - 1;
    *var result = 3 * 5;
    /var result = 3 / 5; // 0.6
    整除~/var result = 3 ~/ 5; // 0
    取余%var result = 5 % 3; // 2

    条件运算符

    名称运算符例子
    大于>2 > 1
    小于<1 < 2
    等于==1 == 1
    不等于!=3 != 4
    大于等于>=5 >= 4
    小于等于<=4 <= 5

    逻辑运算符

    名称运算符例子
    ||2 > 1 || 3 < 1
    &&2 > 1 && 3 < 1
    !(2 > 1)

    位运算符

    名称运算符
    位与&
    位或|
    位非~
    异或^
    左移<<
    右移>>

    三目运算符

    // condition ? expr1 : expr2
    var isOpened = (value == 1) ? true : false;
    

    空安全运算符

    操作符解释
    result = expr1 ?? expr2若expr1为null, 返回expr2的值,否则返回expr1的值
    expr1 ??= expr2若expr1为null, 则把expr2的值赋值给expr1
    result = expr1?.value若expr1为null, 就返回null,否则就返回expr1.value的值
    main() {
        var choice = question.choice ?? 'A';
        // 等价于
        var choice2;
        if(question.choice == null) {
            choice2 = 'A';
        } else {
            choice2 = question.choice;
        }
    }
    
    main() {
        var choice = question.choice ?? 'A';
        // 等价于
        var choice2;
        if(question.choice == null) {
           choice2 = 'A';
        } else {
            choice2 = question.choice;
        }
    }
    
    main() {
        var choice = question?.choice;
        // 等价于
        if(question == null){
            return null;
        } else {
            return question.choice;
        }
    }
    
    main() {
        question?.commit();
        // 等价于
        if(question == null){
            return; // 不执行 commit()
        } else {
            question.commit(); // 执行commit方法
        }
    }
    

    级联操作符(..)

    级联操作符是 .., 可以让你对一个对象中字段进行链式调用操作,类似Kotlin中的apply或run标准库函数的使用。

    question
        ..id = '10001'
        ..stem = '第一题: xxxxxx'
        ..choices = <String> ['A','B','C','D']
        ..hint = '听音频做题';
    

    Kotlin中的run函数实现对比

    question.run {
        id = '10001'
        stem = '第一题: xxxxxx'
        choices = <String> ['A','B','C','D']
        hint = '听音频做题'
    }
    

    运算符重载

    在dart支持运算符自定义重载,使用 operator 关键字定义重载函数

    class Vip {
        final int level;
        final int score;
    
        const Vip(this.level, this.score);
    
        bool operator > (Vip other) =>
            level > other.level || (level == other.level && score > other.score);
    
        bool operator < (Vip other) =>
            level < other.level || (level == other.level && score < other.score);
    
        // 注意: 这段代码可能在高版本的Dart中会报错,在低版本是OK的
        bool operator == (Vip other) =>
            level == other.level && score == other.level;
    
        // 上述代码在高版本 Dart 中,Object 中已经重载了 ==,
        // 所以需要加上 covariant 关键字重写这个重载函数。
        @override
        bool operator == (covariant Vip other) =>
            (level == other.level && score == other.score);
    
        // 伴随着你还需要重写 hashCode,至于什么原因大家应该都知道
        @override
        int get hashCode => super.hashCode;
    }
    
    main() {
        var userVip1 = Vip(4, 3500);
        var userVip2 = Vip(4, 1200);
        if(userVip1 > userVip2) {
            print('userVip1 is super vip');
        } else if(userVip1 < userVip2) {
            print('userVip2 is super vip');
        }
    }
    

    异常

    Dart 中的异常捕获方法和 Java,Kotlin 类似,使用的也是 try-catch-finally,对特定异常的捕获使用 on 关键字,Dart 中的常见异常有:

    • NoSuchMethodError:当在一个对象上调用一个该对象没有实现的函数会抛出该错误。
    • ArgumentError:调用函数的参数不合法会抛出这个错误。
    main() {
        int num = 18;
        int result = 0;
        try {
            result = num ~/ 0;
        } catch (e) { // 捕获到IntegerDivisionByZeroException
            print(e.toString());
        } finally {
            print('$result');
        }
    }
    
    //使用on关键字捕获特定的异常
    main() {
        int num = 18;
        int result = 0;
        try {
            result = num ~/ 0;
        } on IntegerDivisionByZeroException catch (e) { // 捕获特定异常
            print(e.toString());
        } finally {
            print('$result');
        }
    }
    

    函数

    在 Dart 中函数的地位一点都不亚于对象,支持闭包和高阶函数,而且 Dart 中的函数也会比 Java 要灵活的多,而且 Kotlin 中的一些函数特性,它也支持甚至比 Kotlin 支持的更全面。比如支持默认值参数、可选参数、命名参数等。

    函数的基本用法

    main() {
        print('sum is ${sum(2, 5)}');
    }
    
    num sum(num a, num b) {
        return a + b;
    }
    

    函数参数列表传参规则

    // num a, num b, num c, num d 最普通的传参:
    // 调用时,参数个数和参数顺序必须固定。
    add1(num a, num b, num c, num d) {
        print(a + b + c + d);
    }
    
    // [num a, num b, num c, num d] 传参:
    // 调用时,参数个数不固定,但是参数顺序需要一一对应, 不支持命名参数。
    add2([num a, num b, num c, num d]) {
        print(a + b + c + d);
    }
    
    // {num a, num b, num c, num d} 传参:
    // 调用时,参数个数不固定,参数顺序也可以不固定,支持命名参数,也叫可选参数,
    // 是 Dart 中的一大特性,这就是为啥 Flutter 代码那么多可选属性,大量使用可选参数。
    add3({num a, num b, num c, num d}) {
        print(a + b + c + d);
    }
    
    // num a, num b, {num c, num d} 传参:
    // 调用时,a, b 参数个数固定顺序固定,c, d 参数个数和顺序也可以不固定。
    add4(num a, num b, {num c, num d}) {
        print(a + b + c + d);
    }
    
    main() {
        // 最普通的传参: 调用时,参数个数和参数顺序必须固定。
        add1(100, 100, 100, 100);
        // 调用时,参数个数不固定,但是参数顺序需要一一对应, 不支持命名参数(也就意味着顺序不变)。
        add2(100, 100);
        // 调用时,参数个数不固定,参数顺序也可以不固定,支持命名参数(也就意味着顺序可变)。
        add3(b: 200, a: 200, c: 100, d: 100);
        // 调用时,a, b 参数个数固定顺序笃定,c, d 参数个数和顺序也可以不固定。
        add4(100, 100, d: 100, c: 100);
    }
    

    函数默认参数和可选参数

    Dart 中函数的默认值参数和可选参数和 Kotlin 中默认值参数和命名参数一致,只是写法上不同而已。

    // d 就是默认值参数,给的默认值是 100
    add3({num a, num b, num c, num d = 100}) {
        print(a + b + c + d);
    }
    
    main() {
        add3(b: 200, a: 100, c: 800);
    }
    

    函数类型与高阶函数

    在 Dart 中函数也是一种类型 Function,可以作为函数参数传递,也可以作为返回值。类似 Kotlin 中的 FunctionN 系列函数。

    main() {
        Function square = (a) {
            return a * a;
        };
        Function square2 = (a) {
            return a * a * a;
        };
        add(3, 4, square, square2)
    }
    
    num add(num a, num b, [Function op, Function op2]) {
        //函数作为参数传递
        return op(a) + op2(b);
    }
    

    函数的简化以及箭头函数

    在 Dart 中如果在函数体内只有一个表达式,那么就可以使用箭头函数来简化代码,这点也和Kotlin类似,只不过在Kotlin中人家叫lambda表达式,只是写法上不一样而已。

    add4(num a, num b, {num c, num d}) {
        print(a + b + c + d);
    }
    
    add5(num a, num b, {num c, num d}) => print(a + b + c + d);
    

    面向对象

    在 Dart 中一切皆是对象,所以面向对象在Dart中依然举足轻重,下面就先通过一个简单的例子认识下 Dart 的面向对象,后续会继续深入。

    类的基本定义和使用

    abstract class Person {
        String name;
        int age;
        double height;
    
        // 注意,这里写法可能大家没见过, 这点和 Java 是不一样,这里实际上是一个 Dart 的语法糖。
        // 但是这里不如 Kotlin,Kotlin 是直接把 this.name 传值的过程都省了。
        Person(this.name, this.age, this.height);
    
        // 与上述的等价代码,当然这也是Java中必须要写的代码
        Person(String name, int age, double height) {
            this.name = name;
            this.age = age;
            this.height = height;
        }
    
        // 然而 Kotlin 很彻底只需要声明属性就行,下面是 Kotlin 实现代码
        abstract class Person(val name: String, val age: Int, val height: Double)
    }
    
    // 和 Java 一样同时使用 extends 关键字表示继承
    class Student extends Person {
        // 在 Dart 里:类名(变量,变量,...) 是构造函数的写法,
        // `:super()` 表示该构造调用父类,这里构造时传入三个参数。
        Student(String name, int age, double height, double grade): super(name, age, height);
    }
    

    类中属性的 getter 和 setter 访问器(类似 Kotlin)

    abstract class Person {
        // 相当于kotlin中的var 修饰的变量有setter、getter访问器,在dart中没有访问权限,
        // 默认 `_` 下划线开头变量表示私有权限,外部文件无法访问。
        String _name;
    
        // 相当于kotlin中的val 修饰的变量只有getter访问器
        final int _age;
    
        //这是上述简写形式
        Person(this._name, this._age);
    
        // 使用 set 关键字 计算属性 自定义 `setter` 访问器
        set name(String name) => _name = name;
    
        // 使用 get 关键字 计算属性 自定义 `getter` 访问器
        bool get isStudent => _age > 18;
    }
    

    只是了解 Dart 语法时顺手重新排了个版,后续文章可以看原作者的专栏:Flutter 深入浅出系列