Dart语法篇之基础语法(一)

简述:编程

又是一段新的开始,Dart这门语言相信不少人都是经过Flutter这个框架才了解的,由于Flutter相比Dart更被咱们所熟知。不少人迟迟不肯尝试Flutter缘由大多数是由于学习成本高,显然摆在面前的是须要去从新学习一门新的语言dart,而后再去学习一个开发框架Flutter,再加上不少莫名奇妙的坑,不说多的就从Github上Flutter项目issue数来看坑是着实很多,因此不少人也就望而却步了。固然这个问题是一个新的技术框架刚开始均可能存在的,但咱们更须要看到Flutter框架跨平台技术思想先进性。swift

为何要开始一系列Dart相关的文章?数组

很简单,就是为了更好地开发Flutter, 其实开发Flutter使用Dart的核心知识点并不须要太过于全面,有些东西根本用不到,因此该系列文章也将是有选择性选取Dart一些经常使用技术点讲解。另外一方面,读过我文章的小伙伴就知道我是Kotlin的狂热忠实粉, 其实语言都是相通,你能够从Dart身上又能看到Kotlin的身影,因此我上手Dart很是快,能够对比着学习。因此后期Dart文章我会将Dart与Kotlin做为对比讲解,因此若是你学过Kotlin那么恭喜你,上手Dart将会很是快。安全

该系列Dart文章会讲哪些内容呢?markdown

本系列文章主要会涉及如下内容: dart基本语法、变量常量和类型推导、集合、函数、面向对象的Mixins、泛型、生成器函数、Async和Await、Stream和Future、Isolate和EventLoop以及最后基本介绍下DartVM的工做原理。闭包

1、Hello Dart

这是第一个Hello Dart程序,不少程序入口都是从main函数开始,因此dart也不例外,一块儿来看下百变的main函数app

//main标准写法
void main() {
  print('Hello World!');//注意: Dart和Java同样表达式以分号结尾,写习惯Kotlin的小伙伴须要注意了, 这多是你从Kotlin转Dart最大不适之一。
}

//dart中void类型,做为函数返回值类型能够省略
main() {
  print('Hello World!');  
}

//若是函数内部只有一个表达式,能够省略大括号,使用"=>"箭头函数; 
//而对于Kotlin则是若是只有一个表达式,能够省略大括号,使用"="链接,相似 fun main(args: Array<String>) = println('Hello World!')
void main() => print('Hello World!');

//最简写形式
main() => print('Hello World!');
复制代码

2、数据类型

在dart中的一切皆是对象,包括数字、布尔值、函数等,它们和Java同样都继承于Object, 因此它们的默认值也就是null. 在dart主要有: 布尔类型bool、数字类型num(数字类型又分为int,double,而且二者父类都是num)、字符串类型String、集合类型(List, Set, Map)、Runes类和Symbols类型(后两个用的并不太多)框架

一、布尔类型(bool)

在dart中和C语言同样都是使用bool来声明一个布尔类型变量或常量,而在Kotlin则是使用Boolean 来声明,可是一致的是它对应的值只有两个true和false.编程语言

main() {
    bool isClosed = true;//注意,dart仍是和Java相似的 [类型][变量名]方式声明,这个和Kotlin的 [变量名]:[类型]不同.
    bool isOpened = false;
}
复制代码

二、数字类型(num、int、double)

在dart中num、int、double都是类,而后int、double都继承num抽象类,这点和Kotlin很相似,在Kotlin中Number、Int、Double都是类,而后Int、Double都继承于Number. 注意,可是在dart中没有float, short, long类型ide

![](/Users/mikyou/Library/Application Support/marktext/images/2019-10-24-22-02-40-image.png)

main() {
    double pi = 3.141592653;
    int width = 200;
    int height = 300;
    print(width / height);//注意:这里和Kotlin、Java都不同,两个int类型相除是double类型小数,而不是整除后的整数。
    print(width ~/ height);//注意: 这才是dart整除正确姿式
}
复制代码

此外和Java、Kotlin同样,dart也拥有一些数字经常使用的函数:

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)

在Dart中支持单引号、双引号、三引号以及$字符串模板用法和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}";//表达式的值引用
}
复制代码

和Kotlin同样,dart中也有不少字符串操做的方法,好比字符串拆分、子串等

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类型

在Dart中的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类型

在Dart中还有一个和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
}
复制代码

3、变量和常量

一、var关键字

在dart中可使用var来替代具体类型的声明,会自动推导变量的类型,这是由于var并非直接存储值,而是存储值的对象引用,因此var能够声明任何变量。这一点和Kotlin不同,在Kotlin中声明可变的变量都必须须要使用var关键字,而Kotlin的类型推导是默认行为和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声明变量的时候,须要注意的是: 若是var声明的变量开始不初始化,不只值能够改变它的类型也是能够被修改的,可是一旦开始初始化赋值后,它的类型就肯定了,后续不能被改变。

main() {
  var color; // 仅有声明未赋值的时候,这里的color的类型是dynamic,因此它的类型是能够变的 
  color = 'red';
  print(color is String); //true 
  color = 0xffff0000;
  print(color is int); //true 

  var colorValue = 0xffff0000; //声明时并赋值,这里colorValue类型已经推导出为int,而且肯定了类型 
  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定义常量
}
复制代码

4、集合(List、Set、Map)

一、集合List

在dart中的List和Kotlin仍是很大的区别,换句话说Dart整个集合类型系统的划分都和Kotlin都不同,好比Dart中集合就没有严格区分红可变集合(Kotlin中MutableList)和不变集合(Kotlin中的List),在使用方式上你会感受它更像数组,可是它是能够随意对元素增删改为的。

  • List初始化方式

    main() {
        List<String> colorList = ['red', 'yellow', 'blue', 'green'];//直接使用[]形式初始化
        var colorList = <String> ['red', 'yellow', 'blue', 'green'];
    }
    复制代码
  • List经常使用的函数

    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));//获取集合中某个范围元素
        print(colorList.join('<--->'));//相似Kotlin中的joinToString方法,输出: red<--->yellow<--->blue<--->green
        print(colorList.isEmpty);
        print(colorList.contains('green'));    
    }
    复制代码
  • List的遍历方式

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

二、集合Set

集合Set和列表List的区别在于 集合中的元素是不能重复 的。因此添加剧复的元素时会返回false,表示添加不成功.

  • Set初始化方式

    main() {
        Set<String> colorSet= {'red', 'yellow', 'blue', 'green'};//直接使用{}形式初始化
        var colorList = <String> {'red', 'yellow', 'blue', 'green'};
    }
    复制代码
  • 集合中的交、并、补集,在Kotlin并无直接给到计算集合交、并、补的API

    main() {
        var colorSet1 = {'red', 'yellow', 'blue', 'green'};
        var colorSet2 = {'black', 'yellow', 'blue', 'green', 'white'};
        print(colorSet1.intersection(colorSet2));//交集-->输出: {'yellow', 'blue', 'green'}
        print(colorSet1.union(colorSet2));//并集--->输出: {'black', 'red', 'yellow', 'blue', 'green', 'white'}
        print(colorSet1.difference(colorSet2));//补集--->输出: {'red'}
    }
    复制代码
  • Set的遍历方式(和List同样)

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

三、集合Map

集合Map和Kotlin相似,key-value形式存储,而且 Map对象的中key是不能重复的

  • Map初始化方式

    main() {
        Map<String, int> colorMap = {'white': 0xffffffff, 'black':0xff000000};//使用{key:value}形式初始化
     var colorMap = <String, int>{'white': 0xffffffff, 'black':0xff000000};
    }
    复制代码
  • 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的元素
    }
    复制代码
  • 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'));
    }
    复制代码
  • Map.fromIterables将List集合转化成Map

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

四、集合经常使用的操做符

dart对于集合操做的也很是符合现代语言的特色,含有丰富的集合操做符API,可让你处理结构化的数据更加简单。

main() {
  List<String> colorList = ['red', 'yellow', 'blue', 'green'];
  //forEach箭头函数遍历
  colorList.forEach((color) => {print(color)});
  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
  print(numbers.firstWhere((num) => num == 5, orElse: () => -1)); //注意: 若是没有找到,执行orElse代码块,可返回一个指定的默认值

  //singleWhere函数的使用,返回符合条件的第一个元素,若是没找到返回null,可是前提是集合中只有一个符合条件的元素, 不然就会抛出异常
  print(numbers.singleWhere((num) => num == 4, orElse: () => -1)); //注意: 若是没有找到,执行orElse代码块,可返回一个指定的默认值

  //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 ])}');
}
复制代码

5、流程控制

一、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和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(断言)

在dart中若是条件表达式结果不知足条件,则可使用 assert 语句中断代码的执行。特别是在Flutter源码中随处可见都是assert断言的使用。注意: 断言只在检查模式下运行有效,若是在生产模式运行,则断言不会执行。

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

6、运算符

一、算术运算符

名称 运算符 例子
+ 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的值
  • 一、result = expr1 ?? expr2

    若是发现expr1为null,就返回expr2的值,不然就返回expr1的值, 这个相似于Kotlin中的 result = expr1 ?: expr2

    main() {
        var choice = question.choice ?? 'A';
        //等价于
        var choice2;
        if(question.choice == null) {
            choice2 = 'A';
        } else {
            choice2 = question.choice;
        }
    }
    复制代码
  • 二、expr1 ??= expr2 等价于 expr1 = expr1 ?? expr2 (转化成第一种)

    main() {
        var choice ??= 'A';
        //等价于
        if(choice == null) {
            choice = 'A';
        }
    }
    复制代码
  • 三、result = expr1?.value

    若是expr1不为null就返回expr1.value,不然就会返回null, 相似Kotlin中的 ?. 若是expr1不为null,就执行后者

    var choice = question?.choice;
    //等价于
    if(question == null){
        return null;
    } else {
        return question.choice;
    }
    
    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 = listOf('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);

  bool operator ==(Vip other) =>
      level == other.level &&
      score == other.level; //注意: 这段代码可能在高版本的Dart中会报错,在低版本是OK的
  //上述代码,在高版本Dart中,Object中已经重载了==,因此须要加上covariant关键字重写这个重载函数。
  @override
  bool operator ==(covariant Vip other) =>
      (level == other.level && score == other.score);

  @override
  int get hashCode => super.hashCode; //伴随着你还须要重写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');
    }
}
复制代码

7、异常

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');
  }
}
复制代码

8、函数

在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); //调用时,参数个数不固定,参数顺序也能够不固定,支持命名参数(也就意味着顺序可变)
  add4(100, 100, d: 100, c: 100); //调用时,a,b参数个数固定顺序笃定,c,d参数个数和顺序也能够不固定
}
复制代码

三、函数默认参数和可选参数(以及与Kotlin对比)

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

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

main() {
    add3(b: 200, a: 100, c: 800);
}
复制代码

与Kotlin对比

fun add3(a: Int, b: Int, c: Int, d: Int = 100) {
    println(a + b + c + d)
}

fun main(args: Array<String>) {
    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);
复制代码

9、面向对象

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

一、类的基本定义和使用

abstract class Person {
    String name;
    int age;
    double height;
    Person(this.name, this.age, this.height);//注意,这里写法可能你们没见过, 这点和Java是不同,这里其实是一个dart的语法糖。可是这里不如Kotlin,Kotlin是直接把this.name传值的过程都省了。
    //与上述的等价代码,固然这也是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) } class Student extends Person {//和Java同样同时使用extends关键字表示继承
    Student(String name, int age, double height, double grade): super(name, age, height);//在 Dart里:类名(变量,变量,...) 是构造函数的写法, :super()表示该构造调用父类,这里构造时传入三个参数
}
复制代码

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

abstract class Person {
  String _name; ////至关于kotlin中的var 修饰的变量有setter、getter访问器,在dart中没有访问权限, 默认_下划线开头变量表示私有权限,外部文件没法访问
  final int _age;//至关于kotlin中的val 修饰的变量只有getter访问器
  Person(this._name, this._age); //这是上述简写形式

  //使用set关键字 计算属性 自定义setter访问器
  set name(String name) => _name = name;
  //使用get关键字 计算属性 自定义getter访问器
  bool get isStudent => _age > 18;
}
复制代码

总结

这是dart的第一篇文章,主要就是从总体上介绍了下dart的语法,固然里面还有一些东西须要深刻,后续会继续深刻探讨。总体看下有没有以为Kotlin和dart语法很像,其实里面有不少特性都是现代编程语言的特性,包括你在其余语言中一样能看到好比swift等。就到这里,后面继续聊dart和flutter...

相关文章
相关标签/搜索