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

本文收录于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的基本语法和内置类型阐述完毕。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,814评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,124评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,814评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,924评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,815评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,562评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,944评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,582评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,859评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,881评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,700评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,493评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,943评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,115评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,413评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,978评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,182评论 2 339

推荐阅读更多精彩内容