美文网首页dart入门潜修
dart入门潜修基础篇之基本语法和内置类型

dart入门潜修基础篇之基本语法和内置类型

作者: 寒潇2018 | 来源:发表于2019-01-29 17:08 被阅读0次

    本文收录于dart入门潜修系列教程

    创作不易,转载还请备注。

    前言

    本篇文章会对dart语言的基本语法和内置类型做一个整体的阐述。

    变量

    dart为变量提供一个关键字var,这与js、kotlin等都很像,var只是声明一个变量,至于这个变量是个什么类型则由“类型关键字”来决定,如下所示:

    //定义了一个变量var1,此时没有指定var1的类型,
    //则由dart编译器自动推断:即var1是个字符串
      var var1 = "test";
    //显示指定变量str的类型为String
      String str = "test";
    

    在dart中一切都是对象(包括下面提到的内置类型)。因此,var var1 = "test"这句语句,实际上表达的意思是:有一个字符串对象test,其地址保存在了var1变量中。即var1实际上保存的是对象的引用地址,而不是对象本身,这点与很多面向对象的语言一致。

    既然dart中一切都是对象,那么如果我们在定义的时候没有对其进行初始化,那么其默认值是什么?这个有朋友很容易推断出来,在其他语言中,对象的默认值显然是null!确实如此,dart中的变量默认值就是null,但是需要特别注意的是,其内置的诸如数字类型、布尔类型等的默认值同样是null,因为他们也是对象,如下所示:

    void main() {
      int i;
      print(i);//打印'null'
      bool j;
      print(j);//打印'null'
    }
    

    在当前其他一些主流的语言中(比如java),内置的int、bool类型默认值是永远不可能为null的,所以如果之前学习的是java这类的语言,要特别注意这一点。

    常量

    除了变量外,dart还支持常量,dart中修饰常量同样有两个关键字:final和const。final变量只能被赋值一次,表示运行时常量,而const修饰的变量则表示是编译时常量,关于运行时常量和编译时常量,在我的另一个系列文章----->kotlin系列文章中的kotlin入门潜修之类和对象篇—属性和字段这篇文章中有过详细阐述(编译时常量章节)。这里再说下二者的区别:编译时常量,顾名思义,就是在编译的时候就可以确定的常量,即编译器编译成可执行文件的时候就已经保存了该常量值;而运行时常量则只能在运行的时候才可以获取其对应的常量值,编译器编译时只保证代码中没有其他地方可再次修改其值,这也是为啥被称为常量的原因。

    dart中编译时常量和运行时常量示例如下所示:

    void main() {
      final str = "hello word";//运行时常量
      const str2 = "hello word";//编译时常量
      final String str3 = "hello word";//运行时常量,显示指定str3的类型
    }
    

    上面三个都是"常量",均无法再次进行赋值。在dart中,const实际上是隐含包含有final修饰符的,即const修饰的的常量一定是final的。

    再来看个关于常量的例子,如下所示:

      var arr = const [];
      arr = [1, 2, 3];//示例1,正确
      final arr1 = const [];
      arr1 = [1, 2, 4];//示例2,错误,无法再被赋值
      const arr2 = [];
      arr2 = [1, 3, 4];//示例3,错误,无法再被赋值
    

    首先需要注意区分示例1和示例2的区别,示例1表示arr是个变量,其指向了一个包含编译时常量元素的引用地址,即arr本身并不是常量,只是其包含的元素是常量,所以我们可以对其进行二次赋值;示例2是错误的,因为arr1是final的,无法再进行赋值;示例3的错误更是显而易见的,使用const修饰的也无法被赋值。

    了解过dart中的变量、常量的定义之后,下面来看下kotlin中内置的基本数据类型。

    内置类型

    numbers(数字类型)

    不像其他语言,dart的数字类型只有两种,一种是整型,使用int关键字修饰;一种是浮点型,使用double关键字修饰。

    其中int类型的最大长度是64位,但这个会依赖于具体的平台,因为dart支持多种平台,比如在dart 虚拟机上,int的表示范围是-263 to 263 - 1,而当dart被编译为javascript的时候其表示范围为-253 to 253 - 1。

    double类型最大长度也是64位,遵循IEEE 754标准。int和double都是num类型的子类,num定义了一些基本的运算操作,比如加减乘除等,dart中数字的使用示例如下所示:

    void main() {
      int i = 1;//定义一个整型变量i
      double j = 2.1;//定义一个小数j
      num result = i + j;//定义了一个num类型的result
      print(result);//打印3.1
    }
    

    上面代码演示了数字类型的使用,其中在第三行中,我们使用num来接收i+j的结果,这是允许的,因为前面说过num是int和double的父类,这是面向对象语言的基本特点。下面来看下int和double类的声明,如下所示:

    //整型int类的定义
    abstract class int extends num {...}
    //double类型的定义
    abstract class double extends num {...}
    //这就是num的定义
    abstract class num implements Comparable<num> {
      bool operator ==(Object other);
      num operator +(num other);
      num operator -(num other);
      int operator <<(int shiftAmount);
     //省略内容...
    }
    

    上面代码展示了数字类型的相关定义,也验证了我们前面的说法。从定义也可以看出,数字类型的默认值为什么为null,因为他们都是class类型,对应的实例变量如果没有被赋值,其默认值就是null。

    实际上,数字类型除了提供了这些简便的操作符外,还提供了一些便利的方法,如求绝对值、取整等方法,来看几个示例:

    void main() {
      int i = -1; //定义一个整型变量i
      double j = 2.1; //定义一个小数j
      print(i.abs());//求i的绝对值,打印 ‘1’
      print(j.ceil());//求j的向上最大整数,打印'3'
      print(j.floor());//求j的向下的最大整数,打印'2'
      print(j.round());//求离j最近的整数,四舍五入,打印'2'
      print(j.truncate());//截取掉小数点取整,打印'2'
      
      j = 2.6;//验证小数位超过0.5的情形
      print(j.round());//求离j最近的整数,四舍五入,打印'3'
      print(j.truncate());//截取掉小数点取整,打印'2'
      print(j.clamp(1,3));//如果j再1-3之间则返回j,否则返回离其最近的边界值,这里打印j的值 ‘2.6’
      print(j.clamp(3,4));//打印‘3’,原理同上
      print(j.clamp(1,2));//打印‘2’,原理同上
    }
    

    booleans

    dart中为布尔值提供了bool关键字,所谓布尔值就是非真既假的表达。在dart中使用bool还是需要稍加注意的,看个例子:

    void main() {
      bool isOk;
      print(isOk ? "is ok" : "is not ok");//!!!编译错误
    }
    

    是的,上面代码会编译错误!原因是isOk没有被赋值,其默认值为null,而null不能作为bool表达式,所以在使用bool值之前一定要进行初始化,如下所示:

    void main() {
      bool isOk = true;
      print(isOk ? "is ok" : "is not ok");//打印'is ok'
    }
    

    其实null在dart中是所有变量的“通病”,因为dart中一切都是对象,所以在做逻辑之前,一定要考虑变量值可能为null的情况。

    dart中的布尔值只有两个对象值:true和false,这两个布尔值实际上是个编译常量。在dart中,除了bool类型之外,其他类型都无法用在if表达式和assert方法中,如下所示:

      var str = '';
      if (str) {//错误,str是个字符串类型,无法用于if表达式
      }
    
      if(str != null){//正确,str != null返回了bool值
      }
    

    Strings

    dart中的字符串是用utf-16编码的字符序列。在dart中,创建字符串有两种方法:使用双引号和单引号,如下所示:

    void main() {
      var str1 = "hello word";//定义了一个字符串str1
      var str2 = 'hello word';//定义了一个字符串str2
      var str1AndStr2 = str1 + str2;//可以使用+号操作符,拼接两个字符串
      var newStr1 = "new str1 say: " + str1;//同上
      var newStr2 = "new str2 say: $str2";//也可以使用$获取字符串变量的值
      var str3 = "`hello world'\"";//使用\转义特殊字符串
    //dart同样提供了这种拼接形式,此时将会忽略字符串之外的
    //换行和空格,此处打印 Hello world end...
      var concatenateStr = 'Hello '
          'world'
          " end...";
    //三引号表示保持书写的格式进行打印,即写的是什么格式就打印什么格式。
      var concatenateStr2 = '''Hello
          world
          end..''';
      print(concatenateStr2);
    }
    

    lists (列表或者数组)

    几乎所有语言都有数组,表示有序的数据集合。除了数组之外,很多语言还提供了列表(list),列表底层有多种实现方式,数组就是其底层实现的常见方式之一。在dart中,数组就是包含对象的列表,因此他们统称为lists。换句话说,当提到dart中的lists时,其实就是数组的概念。

    列表的示例如下所示:

    void main() {
      var list = [1, 2, 3];//定义了一个数据集合list
      list[0] = 100;//可以通过下标进行赋值
      for (int i = 0; i < list.length; i++) {//打印list中的各个元素
        print(list[i]);
      }
    //定义了一个包含有编译时常量的列表list2
      var list2 = const[1, 2, 3];
      list2[0] = 200;//!!!编译错误,编译时常量无法被重新赋值
    }
    

    上面list的写法是字面量写法,我们还可以通过dart提供的List类型来完成上述功能,如下所示:

      var list = List();//生成一个List类型的对象
      list.add(1);//添加元素1
      list.add(2);//添加元素2
      print(list);//打印 ‘ [1, 2] ’
    

    上面两种不同的写法,实际上生成的都是一个类型的集合:List<int>,即只能向集合中存入int类型的元素,这里涉及到泛型的概念,将会在后续文章中阐述。

    maps(映射)

    所谓映射就是提供key-value的一个数据存储结构。在dart中key和value可以是任何类型,但是key不能重复,而value可以重复。生成map对象同样有两种方式,一种是通过字面量的形式,一种是使用Map类型,示例如下:

    void main() {
      var map = {//通过字面量定义了一个map对象
        "key1":"hello",
        "key2":"world"
      };
      print(map["key1"]);//打印key1对应的值
      var map2 = Map();//通过Map类型,生成一个对象
      map2["key1"] = "map2 value";//添加 key1 : map2 value映射
      map2[1] = "map2 value2";//添加 1 : map2 value映射
      print(map2);//打印{key1: map2 value, 1: map2 value2}
    }
    

    runes

    dart提供了一些可以使用utf-32编码表示的特殊字符,这些字符会被渲染成各种各样的可视化符号,比如我们常见的表情符、icon标识等,这就是所谓的runes(即神秘意义的符号),举个例子就很容易理解了:

      Runes input = new Runes(
          '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
      print(new String.fromCharCodes(input));
    

    上面代码执行后打印如下:

    ♥  😅  😎  👻  🖖  👍
    

    dart中还有一个Symbol类型,使用#修饰(如#test),其字面量是一个编译时常量,但是实际中基本用不到,所以不再阐述。

    至此,dart的基本语法和内置类型阐述完毕。

    相关文章

      网友评论

        本文标题:dart入门潜修基础篇之基本语法和内置类型

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