美文网首页
Dart(二)基础语法

Dart(二)基础语法

作者: 醉了俗身醒了初心 | 来源:发表于2019-04-11 12:45 被阅读0次

    数据类型

    Dart中所有东西都是对象,包括数字、函数等
    它们都继承自Object,并且默认值都是null(包括数字)因此数字、字符串都可以调用各种方法

    Dart中支持以下数据类型:

    Numbers
    Strings
    Booleans
    List(也就是数组)
    Maps
    

    容器后面再讲,这里先说说常用的字符串和数值类型
    还是先建工程吧!Dart代码如下

    void main()
    {
      //Dart 语言本质上是动态类型语言,类型是可选的
      //可以使用 var 声明变量,也可以使用类型来声明变量
      //一个变量也可以被赋予不同类型的对象
      //但大多数情况,我们不会去改变一个变量的类型
      
      //字符串赋值的时候,可以使用单引号,也可以使用双引号
      var str1 = "Ok?";
      
      //如果使用的是双引号,可以内嵌单引号
      //当然,如果使用的是单引号,可以内嵌双引号,否则需要“\”转义
      //String str2 = ‘It\’s ok!’;
      String str2 = "It's ok!";
      
      //使用三个单引号或者双引号可以多行字符串赋值
      var str3 = """Dart Lang
      Hello,World!""";
      
      //在Dart中,相邻的字符串在编译的时候会自动连接
      //这里发现一个问题,如果多个字符串相邻,中间的字符串不能为空,否则报错
      //但是如果单引号和双引号相邻,即使是空值也不会报错,但相信没有人这么做
      //var name = 'Wang''''Jianfei'; 报错
      var name = 'Wang'' ''Jianfei';
      
      //assert 是语言内置的断言函数,仅在检查模式下有效
      //如果断言失败则程序立刻终止
      assert(name == "Wang Jianfei");
      
      //Dart中字符串不支持“+”操作符,如str1 + str2
      //如果要链接字符串,除了上面诉说,相邻字符串自动连接外
      //还可以使用“$”插入变量的值
      print("Name:$name");
      
      //声明原始字符串,直接在字符串前加字符“r”
      //可以避免“\”的转义作用,在正则表达式里特别有用
      print(r"换行符:\n");
      
      //Dart中数值是num,它有两个子类型:int 和 double
      //int是任意长度的整数,double是双精度浮点数
      var hex = 0xDEADBEEF;
          
      //翻了半天的文档,才找打一个重要的函数:转换进制,英文太不过关了
      //上面提到的字符串插值,还可以插入表达式:${}
      print("整型转换为16进制:$hex —> 0x${hex.toRadixString(16).toUpperCase()}");
    
    }
    
    注:新版本SDK已支持“+”操作符连接字符串
    

    const,final和var的区别

    再聊点const和final,用法和其他语言类似
    在声明变量的时候,除了var,还可以使用const和final
    同时,在使用const和final的时候,可以省略var或者其他类型

    var i = 10;
    const i = 10;
    final i = 10;
    
    int i = 10;
    const int i = 10;
    final int i = 10;
    

    const和final定义的都是常量,值不能改变
    并且在声明的时候就必须初始化
    但是也有细微差别,简单来说

    const定义的是编译时常量,只能用编译时常量来初始化
    final定义的常量可以用变量来初始化
    
    final time = new DateTime.now(); //Ok
    const time = new DateTime.now(); //Error,new DateTime.now()不是const常量
    

    var、final等在左边定义变量的时候,并不关心右边是不是常量
    但是如果右边用了const,那么不管左边如何,右边都必须是常量

    const list = const[1,2,3];//Ok
    const list = [1,2,3];//Error
    
    final list = [1,2,3];//Ok
    final list = const[1,2,3];//Ok
    final list = const[new DateTime.now(),2,3];//Error,const右边必须是常量
    

    函数

    1.函数定义

    首先,函数也是对象,当没有指定返回值的时候,函数返回null
    函数定义方法如下:

    String sayHello(String name)
    {
      return 'Hello $name!';
    }
    

    //is is!操作符判断对象是否为指定类型,如num、String等
    assert(sayHello is Function);

    断言函数assert(),Debug模式下,当表达式的值为false时抛出异常。
    在SDK 1.22.0中,assert()添加了第二个参数message,用于在抛出异常的时候,输出具体信息。

    当然,因为Dart中的类型是可选的,也可以这样写

    sayHello(name)
    {
      return 'Hello $name!';
    }
    

    不过建议明确函数的输入类型和返回类型
    方便修改,也方便阅读
    如果函数只是简单的返回一个表达式的值,可以使用箭头语法 =>expr;
    它等价于{return expr;}
    所以上面的函数也可以这样写

    sayHello(name) => 'Hello $name!';
    

    Dart中匿名函数的写法 (name)=>’Hello $name!’;
    于是可以如下定义匿名函数

    var  sayHello = (name)=>'Hello $name!';
    

    2.函数别名

    当看到用typedef定义函数别名的时候,不自觉的想到了函数指针

    typedef int Add(int a, int b);
    int Subtract(int a, int b) => a - b;
    
    void main()
    {
      print(Substract is Function);
      print(Substract is Add);
    }
    

    上面代码的命名感觉有点误导人的感觉
    如果两个函数的参数和返回值都一样
    那么is操作符就会返回true

    3.函数闭包

    下面的代码有一点需要注意
    初始化变量的时候,参数对应的是函数的参数num n
    调用函数类型变量的时候,参数对应的是返回值中的参数num i

    Function makeSubstract(num n)
    {
      return (num i) => n - i;
    }
    
    void main()
    {
      var x = makeSubstract(5);
      print(x(2));
    }
    

    下面这段很有意思的代码
    需要反应过来一件事:Dart中函数也是对象
    下面的代码应该看得明白,之后会讲控制语句以及容器

    var callbacks = [];
    for (var i = 0; i < 3; i++) {
      // 在列表 callbacks 中添加一个函数对象,这个函数会记住 for 循环中当前 i 的值。
      callbacks.add(() => print('Save $i')); 
    }
    callbacks.forEach((c) => c()); // 分别输出 0 1 2
    

    4.可选参数

    Dart中支持两种可选参数:命名可选参数和位置可选参数
    但两种可选不能同时使用

        命名可选参数使用大括号{},默认值用冒号:
        位置可选参数使用方括号[],默认值用等号=
    

    在SDK 1.21.0中,允许使用操作符 = 或 : 设置命名可选参数的默认值

    在命名可选参数的函数中,大括号外的a为必填参数
    大括号内的参数可以指定0个或多个
    并且与顺序无关,在调用函数的时候需要指明参数名
    没有赋值的参数值为null

    FunX(a, {b, c:3, d:4, e})
    {
      print('$a $b $c $d $e');
    }
    

    在位置可选参数的函数中,大括号内的参数可以指定0个或多个
    在调用的时候参数值会依次按顺序赋值

    FunY(a, [b, c=3, d=4, e])
    {
      print('$a $b $c $d $e');
    }
    
    
    void main()
    {
      FunX(1, b:3, d:5);
      FunY(1, 3, 5);
    }
    

    操作符和流程控制语句

    1、取整

    取整~/操作符之前可能很少看到,代码如下:

    int a = 3;
    int b = 2;
    print(a~/b);//输出1
    

    2、级联

    当你要对一个单一的对象进行一系列的操作的时候
    可以使用级联操作符 ..

    class Person {
        String name;
        String country;
        void setCountry(String country){
          this.country = country;
        }
        String toString() => 'Name:$name\nCountry:$country';
    }
    void main() {
      Person p = new Person();
      p ..name = 'Wang'
        ..setCountry('China');
      print(p);
    }
    

    3、If语句

    If语句的判断条件为bool值,用法和大多语言一样

    if(i<0){
      print('i < 0');
    }else if(i ==0){
      print('i = 0');
    } else {
      print('i > 0');
    }
    

    在checked模式下,如果是非bool值会抛出异常
    而在production模式下,非bool值会被翻译成false

    if (1) {
      print('JavaScript is ok.');
    } else {
      print('Dart in production mode is ok.');
    }
    

    在以前出版的书中有段代码

    if (?device) { // Returns true if the caller specified the parameter.
    //...The user set the value. Do something with it...
    }
    

    大概意思是说判断是否传入参数
    但试了各种情况,这样写的话都会报错,不知道是不是已经过时的原因
    建议判断是否传入参数的时候用 device == null 来替换

    4、循环

    for(int i = 0; i<3; i++) {
      print(i);
    }
    

    如果迭代的对象是容器,那么可以使用forEach或者for-in

    var collection = [0, 1, 2];
    
    collection.forEach((x) => print(x));//forEach的参数为Function
    for(var x in collection) {
      print(x);
    }
    

    另外,while和do-while没有什么变化

    while(boolean){
      //do something
    }
     
    do{
      //do something
    } while(boolean)
    

    5、Switch And Case

    swith的参数可以是num,或者String

    var command = 'OPEN';
    switch (command) {
      case 'CLOSED':
        break;
      case 'OPEN':
        break;
      default:
        print('Default');
    }
    

    这里有一点要注意,如果分句的内容为空,想要fall-through(落空),可以省略break
    如果分句的内容不为空,那么必须加break,否则抛出异常

    var command = 'OPEN';
    switch (command) {
      case 'CLOSED':
        print('CLOSED');
        break;
      case 'OPEN'://产生落空效果,执行下一分句
      case 'NOW_OPEN':
        print('OPEN');
        break;
      default:
        print('Default');
    }
    

    如果你想要fall-through,case语句内容又不为空
    而又不是按顺序落空,那么可以使用continue和标签

    var command = 'CLOSED';
      switch (command) {
        case 'CLOSED':
          print('CLOSED');
          continue nowClosed; // Continues executing at the nowClosed label.
        case 'OPEN':
          print('OPEN');
          break;
        nowClosed: // Runs for both CLOSED and NOW_CLOSED.
        case 'NOW_CLOSED':
          print('NOW_CLOSED');
          break;
      }
    

    6、异常处理

    在Dart中可以抛出非空对象(不仅仅是Exception或Error)作为异常

    throw new ExpectException('值必须大于0!');
    throw '值必须大于0!';

    你可以抛出多个类型的Exception,但是由第一个catch到的分句来处理
    如果catch分句没有指定类型,那么它可以处理任何类型的异常

    try {
          throw 'This a Exception!';
      } on Exception catch(e) {
        print('Unknown exception: $e');
      } catch(e) {
        print('Unknown type: $e');
      }
    

    无论是否发生异常,为了使某些代码得以运行,可以使用finally语句

    try {
          throw 'This a Exception!';
      } catch(e) {//可以试试删除catch语句,只用try...finally是什么效果
        print('Catch Exception: $e');
      } finally {
        print('Close');
      }
    

    相关文章

      网友评论

          本文标题:Dart(二)基础语法

          本文链接:https://www.haomeiwen.com/subject/yyhtwqtx.html