dart 订阅
DART(Dynamic Advertising Reporting Targeting) “动态广告报告与目标定位”,是一种热解析和离子化技术。DART-MS(Direct analysis in real time mass spectrometry)实时直接分析质谱 展开全文
DART(Dynamic Advertising Reporting Targeting) “动态广告报告与目标定位”,是一种热解析和离子化技术。DART-MS(Direct analysis in real time mass spectrometry)实时直接分析质谱
信息
外文名
Direct Analysis in Real Time
类    型
是一种热解析和离子化技术
中文名
DART
中文全称
实时直接分析
DART基本信息
DoubleClick的核心技术,允许各网站及网络通过他们的中央服务器管理他们各自的广告服务及统计报告。依靠部署在全球的广告服务器及独特的分布式系统架构,DART系统提供的可升级性、可靠性及强大功能使该系统能够发布更多的广告。(DoubleClick公司主要从事网络广告管理软件开发与广告服务,对网络广告活动进行集中策划、执行、监控和追踪)新的结构化Web编程语言二、 实时直接分析(Direct Analysis in Real Time)简称DART,是一种热解析和离子化技术。DART操作简单,样品置放于DART源出口和一台LC-MS质谱仪的离子采样口,便可进行分析。适用于分析液、固、气态的各类型样品由美国J. Laramee和R. Cody(美JEOL公司)于2005年发明,现由IonSense公司商品化生产、制造和销售。获得2005年Pittcon大奖。DART已广泛应用于药物发现与开发(ADME)、食品药品安全控制与检测、司法鉴定、临床检验、材料分析、天然产品品质鉴定、及相关化学和生物化学等领域。相比于现行通用的液质联用(LC-MS)技术,DART-MS分析将不再需要繁杂的样品制备和耗时的色谱分离。作为一种“绿色”分析检测技术,DART-MS将不需要化学溶剂的消耗,急剧缩短样品分析周期,和极大地减少对固定资产及人员的投资。该技术在美欧等国的研究与应用已成燎原之势,并在著名大学(如Purdue,Rice,George Washington,U Maryland)、研究院(如Los Almos NL,NRCC Canada,US Army)、跨国制药公司(如Roche,Merck,Amgen,GSK,Pfizer,Eli Lilly)、国家执法部门(如FBI,FDA,EPA)等相继采用。
收起全文
精华内容
参与话题
问答
  • Dart语言——45分钟快速入门(上)

    万次阅读 多人点赞 2019-03-23 00:31:23
    文章目录环境准备安装Dart SDK配置环境变量配置 VSCode 编辑器测试环境基础语法代码注释内置数据类型变量与常量定义变量定义常量内置类型的常用操作数值类型字符串布尔类型列表映射函数定义函数函数的参数命名可选...

    前言

    谷歌推出Flutter跨平台UI框架后,对移动端的开发又产生了新的影响,Flutter采用Dart语言开发,而Flutter为什么选择Dart语言作为唯一的开发语言呢?总的来说,其拥有如下优势

    • Dart可基于AOT(Ahead Of Time)编译,即编译成平台的本地代码,运行性能高。
    • Dart也可基于JIT(Just In Time)编译,编译快速,可热加载,使开发周期加倍提升(Flutter亚秒级有状态热重载)
    • Dart可以更轻松地创建以60fps运行的流畅动画和转场。Dart在没有锁的情况下进行对象分配和垃圾回收
    • Dart语法结合Java与JavaScript语法特点,几乎没有令人不适的怪异语法,使Java程序员倍感亲切,快速上手

    通常来说一门语言要么使用AOT编译,编译慢,开发效率低,或者使用JIT编译,在运行时编译,虽然可以热重载,但是执行效率低,而Dart在这两种之间做出了完美平衡,当开发时使用JIT编译,调试快,所见即所得,开发效率高,当发布时,使用AOT编译,编译成目标平台的本地代码,执行效率高。

    视频课程

    博主发布的相关视频课程

    Flutter全栈式开发之Dart 编程指南
    二维码

    Flutter 全栈式开发指南
    快速上手篇可试看

    环境准备

    安装Dart SDK

    官方下载地址
    共有三种SDK版本选择

    • Flutter
    • Web
    • Server

    本章仅作为Dart编程语法学习,这里建议安装Server版的SDK,然后选择Windows版本进行下载。

    配置环境变量

    在Windows上,通过点击下一步即可安装,安装完成后,需将dart-sdk下的的bin目录添加到系统Path环境变量中。这一步骤是通常的命令配置步骤。

    配置 VSCode 编辑器

    作为Dart语言的学习,不建议下载笨重的IDE,官方提供支持VSCode 编辑器插件,建议使用VSCode 学习。

    官网下载 VSCode编辑器,安装完成后,启动VSCode并在插件商店中搜索Dart进行插件安装。

    测试环境

    在VSCode中新建一个test.dart文件,编写如下代码

    void  main(){
        print("hello world!");
    }
    

    运行后成功在控制台输出hello world!

    基础语法

    代码注释

    Dart中的代码注释基本与Java语言相同

    // 单行注释
    
    /*
     * 多行注释
     */
    
    /**
     * 文档注释
     */
    
    /// 使用三个斜杠开头
    /// 这是Dart特有的文档注释
    

    内置数据类型

    在这里插入图片描述

    在Dart中,所有能够使用变量引用的都是对象,每个对象都是一个类的实例。数字、函数和 null 也都是对象。所有的对象都继承于Object类。

    要注意,没有初始化的变量默认值为 null。数值类型变量的默认值也是 null

    数值类型num有两个具体子类,分别为intdouble,其中int为整数值,范围是-2^532^53之间;double则是64位的双精度浮点数。

    变量与常量

    定义变量

    Dart中定义变量有两种方式,一种是静态类型语言常用的方式,显式指定变量类型,另一种则是动态语言的常用方式,不指定类型,由vm自动推断。

    // 1.通过显式指定类型来定义变量
    String name = "张三";
    num age = 18;
    
    // 2.使用关键字var,不指定类型
    var address = "深南大道";
    var id = 100;
    
    /* 使用var定义变量,即使未显式指定类型,一旦赋值后类型就被固定
     * 因此使用var定义的变量不能改变数据类型
     */
    var number = 19;
    // 以下代码错误,无法运行,number变量已确定为int类型
    number = "2019";
    

    如想动态改变变量的数据类型,应当使用dynamicObject来定义变量。

    // dynamic声明变量
    dynamic var1 = "hello";
    var1 = 19;
    print(var1);    // 19
    
    // Object声明变量
    Object var2 = 20;
    var2 = "Alice";
    print(var2);    // Alice
    

    建议在编写代码时,尽可能显式指定变量类型,这样可以提升代码可读性与调试的便利性。

    定义常量

    Dart中定义常量也有两种方式,一种使用final关键字,同Java中的用法, 一个 final 变量只能赋值一次;另一种是Dart的方式,使用const关键字定义。

    // 1.使用final关键字定义常量
    final height = 10;
    
    // 2.使用const关键字定义常量
    const pi = 3.14;
    

    需要注意,final定义的常量是运行时常量,而const常量则是编译时常量,也就是说final定义常量时,其值可以是一个变量,而const定义的常量,其值必须是一个字面常量值。

    final time = new DateTime.now(); // 正确
    const time = new DateTime.now(); // 错误
    
    
    const list = const[1,2,3];       // 正确
    const list = [1,2,3];            // 错误
    

    内置类型的常用操作

    数值类型

    // String 转 int
    var one = int.parse('1');
    
    // String 转 double
    var onePointOne = double.parse('1.1');
    
    // int 转 String
    String oneAsStr = 1.toString();
    
    // double 转 String
    String piAsStr = 3.14159.toStringAsFixed(2); // 保留两位 '3.14'
    
    // Dart也支持整数位操作,<<、 >>、&、|
    print((3 << 1) == 6);  // 0011 << 1 == 0110
    print((3 >> 1) == 1);  // 0011 >> 1 == 0001
    print((3 | 4)  == 7);  // 0011 | 0100 == 0111
    

    字符串

    值得一提的是,Dart中提供的字符串插值表达式使字符串格式化变得异常方便。

    // 1.Dart可以使用单引号或双引号来创建字符串
    var s1 = "hello";
    var s2 = 'world';
    
    // 2.类似Python,Dart可以使用三引号来创建包含多行的字符串
    var multiLine1 = """你可以像这样,创建一个
    包含了多行的字符串内容
    """;
    
    var multiLine2 = '''你也可以使用三个单引号,创建一个
    包含了多行的字符串内容
    ''';
    
    // 3.类似Python,还可以在字符串字面值的前面加上`r`来创建原始字符串,则该字符串中特殊字符可以不用转义
    var path = r'D:\workspace\code';
    
    // 4.Dart支持使用"+"操作符拼接字符串
    var greet = "hello" + " world";
    
    // 5.Dart提供了插值表达式"${}",也可以用于拼接字符串
    var name = "王五";
    var aStr = "hello,${name}";
    print(aStr);    // hello,王五
    
    // 当仅取变量值时,可以省略花括号
    var aStr2 = "hello,$name"; // hello,王五
    
    // 当拼接的是一个表达式时,则不能省略花括号
    var str1 = "link";
    var str2 = "click ${str1.toUpperCase()}";
    print(str2);   // click LINK
    
    // 6. 与Java不同,Dart使用"=="来比较字符串的内容
    print("hello" == "world");
    

    布尔类型

    Dart中的布尔类型用法同Java,仅有falsetrue两个值,不能使用0、非0或者null、非null来表达falsetrue。与Java不同的是,布尔类型的默认值为null

    bool flags;
    print(flags);    // null
    

    列表

    Dart中列表操作与JavaScript中的数组相似。

    // 创建列表
    var list = [1, 2, 3];
    // 下标从0开始。使用length可以访问list的长度
    print(list[0]);
    print(list.length);
    
    // 可以使用add添加元素
    list.add(5);
    
    // 可在list字面量前添加const关键字,定义一个不可改变的 列表(编译时常量)
    var constantList = const [1, 2, 3];
    constantList[1] = 1;     // 报错
    

    映射

    又称为关联数组,相当于Java中的HashMap

    // 1.通过字面量创建Map
    var gifts = {
      'first' : 'partridge',
      'second': 'turtledoves',
      'fifth' : 'golden rings'
    };
    
    // 2.使用Map类的构造函数创建对象
    var pic = new Map();
    // 往Map中添加键值对
    pic['first'] = 'partridge';
    pic['second'] = 'turtledoves';
    pic['fifth'] = 'golden rings';
    
    // 3.获取Map的长度
    print(pic.length);
    
    // 4.查找Map
    pirnt(pic["first"]);
    print(pic["four"]);    // 键不存在则返回 null
    

    函数

    在Dart中,函数(或方法) 也是对象,它的类型是 Function。 这意味着,函数可以赋值给变量,也可以当做其他函数的参数。

    定义函数

    Dart中定义函数,基本上与Java类似

    String greet(String name){
        return "hello,$name";
    }
    

    在Dart中,类型是可选,可以省略显式的类型,但仍然建议显式指定类型。

    greet(name){
        return "hello,$name";
    }
    

    要注意,函数也是对象,所有函数都有返回值。当没有指定返回值的时候,函数会返回null。当然,如果你强行使用void来修饰函数,则函数真的没有返回值,这种情况就另当别论了。

    函数的参数

    Dart中支持两种可选参数

    • 命名可选参数
    • 位置可选参数

    在Java中通常使用方法重载来实现同名方法的不同参数调用,Dart中则可以通过可选参数来实现相同效果。

    命名可选参数

    先来看一下命名参数,它使用花括号来定义参数列表

    // 定义一个函数,参数列表用花括号包裹
    enableFlags({bool bold, bool hidden}) {
        // do something
    }
    
    // 调用方式,传参时使用"参数名:值"的形式
    enableFlags(hidden:true,bold:false);
    

    如果在定义函数时,给参数列表中的参数设置默认值,则该参数就是可选的,函数调用时可以忽略该参数,使用默认的值。

    // 定义add函数
    add({int x, int y=1, int z=0}){
        print(x + y + z;
    }
    
    // 调用
    add(x:18);              // 19
    add(x:18, y:2, z:10);   // 30
    

    这里需要注意一下,SDK 1.21之前的版本中,命名参数不能使用=号来设置默认值,而SDK 1.21之后,只能使用=号来设置默认值。因此,请检查并升级SDK版本。

    位置可选参数

    位置可选参数使用中括号来定义参数列表,中括号中的参数是可选的

    // 定义add函数
    add(int x, [int y, int z]){
        int result = x;
        if (y !=  null){
            result = result + y;
        }
    
        if (z !=  null){
            result = result + z;
        }
        print(result);
    }
    
    // 调用
    add(18);           // 18
    add(18,12);        // 30
    add(18, 12, 15);   // 45
    

    位置可选参数设置默认值

    // 定义add函数
    add(int x, [int y=0, int z=0]){
        print(x +y+z);
    }
    

    最后需要注意一下命名可选参数位置可选参数的区别,前者中的参数与顺序无关,无需按顺序传参,且传参数时需使用冒号;后者与顺序相关,传参必须依照顺序。

    匿名函数

    大部分函数都有名字,但我们也可以创建没有名字的函数,称为匿名函数,也被称为lambda表达式或者闭包。

    // 定义匿名函数,并将其赋值给一个变量func,注意,函数体最后的花括号处必须有分号结束。
    var func = (x,y){
        return x + y;
    };
    
    print(func(10,11));    // 21
    

    注意,匿名函数与普通函数基本相同,也有参数列表,函数体,只是省去了函数名而已。

    箭头函数

    Dart中的箭头函数与JavaScript中的基本相同。当函数体中只包含一个语句时,我们就可以使用=>箭头语法进行缩写。注意,箭头函数仅仅只是一个简洁表达的语法糖。

    普通函数

    add(num x, num y){
        return x + y;
    }
    
    print(add(18,12));    // 30
    

    箭头函数

    // 与上面的普通函数完全等价
    add(num x, num y) => x + y;
    
    print(add(18,12));    // 30
    

    箭头函数省略了花括号的表达,箭头后面跟一个表达式,函数的返回值也就是这个表达式的值。另外,箭头函数也可以与匿名函数结合,形成匿名箭头函数。

    var func = (num x, num y) => x + y;
    

    运算符

    Dart语言中的运算符与Java中的绝大多数相同。

    算术运算符

    +-*/%同Java语言

    Dart中又多出了一个整除运算符~/,与普通除号的区别是将相除后的结果取整返回。

    类型判定运算符

    以下是Dart增加的类型相关的运算符。

    操作符 解释
    as 用于类型转换
    is 如果对象是指定的类型就返回 True
    is! 如果对象不是指定的类型返回 True

    obj 实现了 T 的接口时, obj is T 才是 true。类似于Java中的instanceof

    Dart中使用 as 操作符把对象转换为特定的类型,如无法转换则会抛出异常,因此在转换前最好使用is运算符进行检测。

    // 将p转换为Person类型再操作
    (p as Person).name = 'Bruce';
    

    条件表达式

    Dart中也支持三目表达式
    condition ? expr1 : expr2

    除此外,Dart还增加了非空条件判断符??
    expr1 ?? expr2
    上述运算表示,如果expr1的值不等于null,则返回其值; 否则执行表达式expr2并返回其结果。

    var str1 =  "Hello";
    var str2 =  "world";
    var result = str1 ?? str2.toUpperCase();
    

    级联运算符

    我们通常使用.操作符调用对象的方法,这在Dart中也是支持的,但是Dart另外增加了一种级联运算符..,用两个点表示。

    级联运算符可以在同一个对象上连续调用多个方法以及访问成员变量。 使用它可以避免创建临时变量, 写出更流畅的代码。

    假如类Person有三个方法,setNamesetAgesave,则可如下调用

    new Person()..setName("Bob")..setAge(20)..save();
    

    使用级联运算符调用方法,无需该方法返回对象本身即可连续的流式的调用该对象的其他方法。

    条件成员访问符

    在Java中很容易碰到恼人的空指针错误,因此在方法调用前需要进行对象的非空判断,这样的判断语句使代码变得冗长,可读性差,不整洁。Dart中则发明了一个新的运算符用于处理此类情况。

    条件成员访问符?.,它和.类似,但是运算符左边的对象不能为null,否则返回null,若对象不为null,则返回对象本身。

    // list1默认值为null
    List list1;
    print(list1?.length);  // null
    
    List list2 = [];
    print(list2?.length);  // 0
    

    分支与循环

    条件分支

    Dart中的条件分支基本与Java相同

    if条件分支

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

    switch条件分支

    // 在switch的case中可以使用整数、字符串、枚举类型和编译时常量
    String command = 'OPEN';
    switch (command) {
      case 'CLOSED':
        break;
      case 'OPEN':
        break;
      default:
        print('Default');
    }
    

    循环语句

    基本循环

    Dart中的基本循环语句与Java相同

    // for循环
    for(int i = 0; i < 9; i++) {
      print(i);
    }
    
    // while循环
    while(true){
      //do something
    }
    
    // do-while循环
    do{
      //do something
    } while(true);
    

    特有循环

    var myList = ['Java','JavaScript','Dart'];
    
    // for...in...循环,类似Java中的增强for
    for (var it in myList ){
        print(it);
    }
    
    // forEach循环。其参数为一个Function对象,这里传入一个匿名函数
    myList.forEach((var it){
        print(it);
    });
    
    // 可以使用匿名箭头函数简写
    myList.forEach((it) => print(it));
    

    使用循环遍历Map

    var myMap = {
    'zhangsan':'201901',
    'lisi':'201902',
    'wangwu':'201902'
    };
    
    // forEach遍历Map
    myMap.forEach((k, v) =>  print("$k : $v"));
    
    // 根据键获取值来遍历。通过keys返回Map中所有键的集合
    for(var k in myMap.keys){
        print("$k : ${myMap[k]}");
    }
    

    下一篇 Dart语言——45分钟快速入门(下)

    关注我的公众号:编程之路从0到1

    编程之路从0到1

    展开全文
  • Dart语法

    千次阅读 2018-10-22 22:28:11
    变量 基本类型 bool done = true; int num = 2; double x = 3.14; final bool visible = false; final int amount = 100; final double y = 2.7;...const double z = 1.2...

    变量

    基本类型

    bool done = true;
    int num = 2;
    double x = 3.14;
    
    final bool visible = false;
    final int amount = 100;
    final double y = 2.7;
    
    const bool debug = true;
    const int sum = 42;
    const double z = 1.2;
    

    跟常用的其他语言不同,Dart 没有 byte、char 和 float,int、double 都是 64 位。final 跟 Java 里的 final 一样,表示一个运行时常量(在程序运行的时候赋值,赋值后值不再改变)。const 表示一个编译时常量,在程序编译的时候它的值就确定了。

    如果你觉得每次写变量类型太麻烦,你应该会喜欢 Dart 的类型推断功能:

    var done = true;
    var num = 2;
    var x = 3.14;
    
    final visible = false;
    final amount = 100;
    final y = 2.7;
    
    const debug = true;
    const sum = 42;
    const z = 1.2;
    

    Dart 里所有的东西都是对象,包括 int、函数。

    String

    var str = ' foo';
    var str2 = str.toUpperCase();
    var str3 = str.trim();
    assert(str == str2);
    assert(!identical(str, str2));
    

    Dart 里的 String 跟 Java 中的一样,是不可变对象;不同的是,检测两个 String 的内容是否一样事,我们使用 == 进行比较;如果要测试两个对象是否是同一个对象(indentity test),使用 identical 函数。

    List、Map 和 Set

    List

    // 使用构造函数创建对象
    // 跟 var list = new List<int>(); 一样
    var list = List<int>();
    list.add(1);
    list.add(2);
    
    // 通过字面量创建对象,list 的泛型参数可以从变量定义推断出来。
    // 推荐使用字面量方式创建对象
    var list2 = [1, 2];
    // 没有元素,显式指定泛型参数为 int
    var list3 = <int>[];
    list3.add(1);
    list3.add(2);
    
    var list4 = const[1, 2];
    // list4 指向的是一个常量,我们不能给它添加元素(不能修改它)
    list4.add(3);       // error
    // list4 本身不是一个常量,所以它可以指向另一个对象
    list4 = [4, 5];     // it's fine
    
    const list5 = [1, 2];
    // 相当于 const list5 = const[1, 2];
    list5.add(3);       // error
    
    // Dart 同样提供了 for-in 循环。
    // 因为语音设计时就考虑到了这个需求,in 在 Dart 里是一个关键字
    var list6 = [1, 3, 5, 7];
    for (var e in list6) {
      print(e);
    }
    

    在 Dart 2 里,创建对象时可以省略 new 关键字,也推荐省略 new。

    Set

    var set = Set<String>();
    set.add('foo');
    set.add('bar');
    assert(set.contains('foo'));
    

    我们只能通过 Set 的构造函数创建实例。

    Map

    var map = Map<String, int>();
    // 添加
    map['foo'] = 1;
    map['bar'] = 3;
    // 修改
    map['foo'] = 4;
    // 对应的 key 不存在时,返回 null
    if (map['foobar'] == null) {
      print('map does not contain foobar');
    }
    
    var map2 = const {
      'foo': 2,
      'bar': 4,
    };
    var map3 = <String, String>{};
    

    dynamic 和 Object

    前面我们说过,Dart 里所有东西都是对象。所有这些对象的父类就是 Object。

    Object o = 'string';
    o = 42;
    o.toString();   // 我们只能调用 Object 支持的方法
    
    dynamic obj = 'string';
    obj['foo'] = 4;  // 可以编译通过,但在运行时会抛出 NoSuchMethodError
    

    Object 和 dynamic 都使得我们可以接收任意类型的参数,但两者的区别非常的大。

    使用 Object 时,我们只是在说接受任意类型,我们需要的是一个 Object。类型系统会保证其类型安全。

    使用 dynamic 则是告诉编译器,我们知道自己在做什么,不用做类型检测。当我们调用一个不存在的方法时,会执行 noSuchMethod() 方法,默认情况下(在 Object 里实现)它会抛出 NoSuchMethodError。

    为了在运行时检测进行类型检测,Dart 提供了一个关键字 is:

    dynamic obj = <String, int>{};
    if (obj is Map<String, int>) {
      // 进过类型判断后,Dart 知道 obj 是一个 Map<String, int>,
      // 所以这里不用强制转换 obj 的类型,即使我们声明 obj 为 Object。
      obj['foo'] = 42;
    }
    
    // 虽然 Dart 也提供了 as 让我们进行类型的强制转换,但为了进来更安全
    // 的转换,更推荐使用 is
    var map = obj as Map<String, int>;
    

    语句

    var success = true;
    if (success) {
      print('done');
    } else {
      print('fail');
    }
    
    for (var i = 0; i < 5; ++i) {
      print(i);
    }
    
    var sum = 0;
    var j = 1;
    do {
      sum += j;
      ++j;
    } while (j < 5);
    
    while (sum-- > 0) {
      print(sum);
    }
    
    var type = 1;
    switch (type) {
      case 0:
        // ...
        break;
      case 1:
        // ..
        break;
      case 2:
        // ...
        break;
      default:
        // ...
        break;
    }
    

    常见的 if/else,do while,while 和 switch 在 Dart 里面都支持。switch 也支持 String 和 enum。

    函数

    最普通的函数看起来跟 Java 里的一样:

    int foo(int x) {
      return 0;
    }
    

    Dart 也支持可选参数:

    void main() {
      print(foo(2));
      print(foo(1, 2));
    }
    
    int foo(int x, [int y]) {
      // 是的,int 也可以是 null
      if (y != null) {
        return x + y;
      }
      return x;
    }
    
    // 结果:
    // 2
    // 3
    

    默认参数也是支持的:

    int foo(int x, [int y = 0]) {
      return x + y;
    }
    

    还能用具名参数(named parameters):

    void main() {
      print(foo(x: 1, y: 2));
      // 具名参数的顺序可以是任意的
      print(foo(y: 3, x: 4));
      // 所有的具名参数都是可选的,这个调用是合法的,但它会导致 foo() 在运行时抛异常
      print(foo());
    }
    
    int foo({int x, int y}) {
      return x + y;
    }
    

    具名参数也可以有默认参数:

    void main() {
      print(foo(x: 1, y: 2));
      print(foo());
    }
    
    int foo({int x = 0, int y = 0}) {
      return x + y;
    }
    

    如果想告诉用户某个具名参数是必须的,可以使用注解 @required:

    int foo({@required int x, @required int y}) {
      return x + y;
    }
    

    @required 是 meta 包里提供的 API,更多的信息读者可以查看 https://pub.dartlang.org/packages/meta。

    函数还可以在函数的内部定义:

    // typedef 在 Dart 里面用于定义函数类型的别名
    typedef Adder = int Function(int, int);
    
    Adder makeAdder(int extra) {
      int adder(int x, int y) {
        return x + y + extra;
      }
      return adder;
    }
    
    void main() {
      var adder = makeAdder(2);
      print(adder(1, 2));
    }
    
    // 结果:
    // 5
    

    像上面这样简单的函数,我们还可以使用 lambda:

    typedef Adder = int Function(int, int);
    
    Adder makeAdder(int extra) {
      return (int x, int y) {
        return x + y + extra;
      };
      // 如果只有一个语句,我们可以使用下面这种更为简洁的形式
      // return (int x, int y) => x + y + extra;
    }
    
    void main() {
      var adder = makeAdder(2);
      print(adder(1, 2));
    }
    

    Dart 里面不仅变量支持类型推断,lambda 的参数也支持自动推断。上面的代码还可以进一步简化为:

    typedef Adder = int Function(int, int);
    
    Adder makeAdder(int extra) {
      // 我们要返回的类型是 Adder,所以 Dart 知道 x, y 都是 int
      return (x, y) => x + y + extra;
    }
    
    void main() {
      var adder = makeAdder(2);
      print(adder(1, 2));
    }
    

    美中不足的是,Dart 不支持函数的重载。

    异常

    抛出异常:

    throw Exception('put your error message here');
    

    捕获异常:

    try {
      // ...
    // 捕获特定类型的异常
    } on FormatException catch (e) {
      // ...
    // 捕获特定类型的异常,但不需要这个对象
    } on Exception {
      // ..
    // 捕获所有异常
    } catch (e) {
      // ...
    } finally {
      // ...
    }
    

    跟 Java 不同的是,Dart 可以抛出任意类型的对象:

    throw 42;
    

    定义一个类:

    class Point2D {
      static const someConst = 2;
    
      int x;
      // 成员变量也可以是 final 的
      final int y;
    
      Point2D(int x, int y) {
        this.x = x;
        this.y = y;
      }
    }
    

    由于这种初始化方式很常见,Dart 提供了更简洁的方式:

    class point2d {
      int x;
      int y;
    
      point2d(this.x, this.y);
    }
    

    此外,还可以使用初始化列表(initializer list)对对象进行初始化:

    class Point2D {
      int x;
      int y;
    
      // 由于是在 initializer list 中,Dart 知道第一个 x 是 this.x,
      // 第二个 x 是构造函数的参数
      Point2D(int x, int y) : x = x, y = y {
        // ...
      }
    }
    

    initializer list 会在构造函数的函数体运行前执行。

    Dart 具有垃圾收集功能,对象的使用跟 Java 里几乎是一样的:

    main() {
      var point = Point2D(1, 2);
      point.x = 4;
      print(point);
    }
    
    class Point2D {
      int x;
      int y;
      Point2D(this.x, this.y);
    
      // 所有的类都继承自 Object,toString() 是 Object 中的方法
      @override
      String toString() {
        // 在字符串的内部可以通过 ${expression} 的方式插入值,如果
        // expression 是一个变量,可以省略花括号
        return "Point2D{x=$x, y=$y}";
      }
    }
    
    // 结果:
    // Point2D{x=4, y=2}
    

    Dart 使用 package 的概念来管理源码和可见性。它没有 public、private 之类的访问权限控制符,默认情况下,所有的符号都是公开的。如果我们不想某个变量对包的外部可见,可以使用下划线开头来给变量命名。

    class _Foo {
      // ...
    }
    
    class Bar {
      int _x;
    }
    

    下面我们使用 Dart 的访问控制,实现一个带偏移量的 Point:

    class OffsetPoint {
      int _x;
      int _y;
      int offset;
    
      OffsetPoint(int x, int y, int offset)
          : _x = x, _y = y, offset = offset {}
    
      // 定义一个 getter
      int get x => _x + offset;
      // getter 不能有参数,连括号都省掉了
      int get y {
        return _y + offset;
      }
      // 定义 setter
      void set x (int x) => _x = x;
      void set y (int y) => _y = y;
    
      @override
      String toString() {
        return "OffsetPoint{x=$x, y=$y}";
      }
    }
    
    main() {
      var point = OffsetPoint(1, 2, 10);
      // 使用 getter/setter 时,就像它是一个普通的成员变量
      print(point.x)
      print(point);
      point.x = 4;
      print(point);
    }
    
    // 结果:
    // 11
    // OffsetPoint{x=11, y=12}
    // OffsetPoint{x=14, y=12}
    

    在 Dart 里继承对象也很简单:

    class Point2D {
      int x;
      int y;
      Point2D(this.x, this.y);
    }
    
    class Point3D extends Point2D {
      int z;
      // 父类的构造函数只能在 initializer list 里调用
      Point3D(int x, int y, int z): z = z, super(x, y) {
      }
    }
    

    但是对象构造时它跟 Java、C++ 都不太一样:

    1. 先执行子类 initializer list,但只初始化自己的成员变量

    2. 初始化父类的成员变量

    3. 执行父类构造函数的函数体

    4. 执行之类构造函数的函数体

    基于这个初始化顺序,推荐是把 super() 放在 initializer list 的最后。此外,在 initializer list 里不能访问 this(也就是说,只能调用静态方法)。

    虽然 Dart 是单继承的,但它也提供了一定程度的多重继承支持:

    abstract class Bark {
      void bark() {
        print('woof');
      }
    }
    
    class Point3D extends Point2D with Bark {
      int z;
      // 父类的构造函数只能在 initializer list 里调用
      Point3D(int x, int y, int z): z = z, super(x, y) {
      }
    }
    
    // 没有其他类需要继承,所以直接 extends Bark 就可以了
    class Foo extends Bark {}
    
    void main() {
      var p = Point3D(1, 2, 3);
      p.bark();
    }
    

    Dart 把支持多重继承的类叫做 mixin。更详细的介绍,读者可以参考https://www.dartlang.org/articles/language/mixins。

    泛型

    class Pair<S, T> {
      S first;
      T second;
      Pair(this.first, this.second);
    }
    
    void main() {
      var p = Pair('hello', 2);
      print(p is Pair<String, int>);
      // is! 也是 Dart 的运算符,下面的语句跟 !(p is Pair<int, int>) 是一样的,
      // 但 is! 读起来跟像英语
      print(p is! Pair<int, int>);
      print(p is Pair);
    }
    
    // 结果:
    // true
    // true
    // true
    

    跟 Java 不同,Dart 的泛型参数类型在运行时是保留的。

    Future

    Dart 是单线程的,主线程由一个事件循环来执行(类似 Android 的主线程)。对于异步代码,我们通过 Future 来获取结果:

    import 'dart:io';
    
    void foo() {
      var file = File('path-to-your-file');
      file.exists()
          .then((exists) => print('file ${exists ? 'exists' : 'not exists'}'))
          .catchError((e) => print(e));
    }
    

    Dart 2 提供了 async 函数,用来简化这种编程范式。下面这段代码的效果跟上面是一样的:

    void foo() async {
      var file = File('path-to-your-file');
      try {
        var exists = await file.exists();
        print('file ${exists ? 'exists' : 'not exists'}');
      } catch (e) {
        print(e);
      }
    }
    

    但是要注意,上面两段代码并不是完全一样的:

    // import 语句用于导入一个包
    import 'dart:io';
    
    void main() {
      foo();
      bar();
    }
    
    void bar() {
      var file = File('path-to-your-file');
      file.exists()
          .then((exists) => print('bar: file ${exists ? 'exists' : 'not exists'}'))
          .catchError((e) => print(e));
      print('bar: after file.exists() returned');
    }
    
    void foo() async {
      var file = File('path-to-your-file');
      try {
        var exists = await file.exists();
        print('bar: file ${exists ? 'exists' : 'not exists'}');
        print('bar: after file.exists() returned');
      } catch (e) {
        print(e);
      }
    }
    
    // 一种可能的结果:
    // bar: after file.exists() returned
    // foo: file not exists
    // foo: after file.exists() returned
    // bar: file not exists
    

    这里的关键在于,bar 函数里面,file.exists() 执行完后,会马上执行下面的语句;而 foo 则会等待结果,然后才继续执行。关于 Future 的更多的细节,强烈建议读者阅读https://webdev.dartlang.org/articles/performance/event-loop。

    展开全文
  • Dart入门?一篇文章就够了!

    千次阅读 2019-08-20 17:54:18
    由于项目采用敏捷开发模式,故本文主要总结和记录 Dart 常用语法,更多高级和生僻用法将在后面开发过程中不定期更新。 First of all 在我们正式接触 Dart 语法之前,需要铭记以下内容,这将会对后续 Dart 语法的学习...

    近期公司准备启动新项目,经过技术团队一番调研,决定采用 Flutter 来开发第一版App,故作此文,常来回顾温习。由于项目采用敏捷开发模式,故本文主要总结和记录 Dart 常用语法,更多高级和生僻用法将在后面开发过程中不定期更新。

    First of all

    在我们正式接触 Dart 语法之前,需要铭记以下内容,这将会对后续 Dart 语法的学习、理解和应用有很大帮助:

    • 万物皆对象, 每个对象都是一个类的实例。在 Dart 中,甚至连数字、方法和 null 都是对象,并且所有的对象都继承于 Object 类。
    • 尽管 Dart 语言是一种强类型语言,但你在类型声明时仍然可以不指定类型,因为 Dart 可以自动进行类型推断。如在代码 var number = 5; 中,number 变量的类型就被推断为 int,当你并不想显式地声明类型时,你可以使用特有的类型 dynamic 来标识。
    • Dart 语言同样支持泛型,如 List<int>List<dynamic>(同 Java 中的 List<Object>)。
    • Dart 语言支持顶级方法(即不与类绑定的方法,如上的 main 方法),以及绑定类和实例的方法(分别对应静态方法和实例方法),而且还支持方法嵌套(同 Python 和 JS)。
    • 同样,Dart 还支持顶级变量,以及在类中定义的变量(如静态变量和实例变量)。
    • 和 Java 不同的是,Dart 没有 publicprotected 以及 private 关键字。它通过给变量或者方法名加上 _ 前缀来将其标识为私有域。

    变量

    你可以通过 var 或者特定的类型来修饰变量,如果变量的类型不是固定的,也可以通过 dynamic 或者 Object 来修饰。如:

    // 类型推断
    var name = 'Bob';
    // 指定类型
    String name = 'Bob';
    // 类型不局限于string
    dynamic name = 'Bob';
    

    默认值

    Dart 中声明时如果未初始化,会被自动初始化为null

    int lineCount;
    assert(lineCount == null);
    

    注:assert 只在开发环境有效,在实际的生产环境无效。

    final 与 const

    finalconst 标识该变量只能被赋值一次,区别在于 final 是运行时赋值,const 是编译时赋值。

    final String nickname = 'Jack';
    // final修饰时, 可省略类型声明
    final name = 'Jack';
    

    const不仅可以用来声明变量,还能用来创建常量值,如:

    // 此时不能在对列表a进行更新操作
    var a = const [1, 2];
    // 注意以下 const 修饰的区别
    var foo = const [];
    const baz = []; // Equivalent to `const []`
    ...
    foo = [1, 2, 3]; // Was const []
    baz = [42]; // Error: Constant variables can't be assigned a value.
    

    数据类型

    Dart 语言支持的数据类型与 Java 类似,但也有所不同,下面我们来按照“求同存异”的法则来分别认识它们。

    数字类型

    Dart 中的数字类型只有两种:Intdouble。与 Java 不同的是,它并没有提供 float 类型。例如,我们可以通过以下方式来定义数字:

    // 定义整型
    var x = 123;
    var hex = 0xDEADBEEF;
    // 定义双精度类型
    var y = 1.199;
    var exponents = 1.42e5;
    
    

    再来看下常用的数据转换该如何执行:

    // String -> int
    var a = int.parse('1');
    assert(a == 1);
    
    // String -> double
    var b = double.parse('1.1');
    assert(b == 1.1);
    
    // int -> String
    String c = 1.toString();
    assert(c == '1');
    
    // double -> String
    String d = 3.14159.toStringAsFixed(2);
    assert(d == '3.14');
    

    int 类型可以执行传统的按位移位( <<>> ),AND( & )和OR( | )运算符,如:

    assert((3 << 1) == 6); // 0011 << 1 == 0110
    assert((3 >> 1) == 1); // 0011 >> 1 == 0001
    assert((3 | 4) == 7);  // 0011 | 0100 == 0111
    

    字符串类型

    字符串的声明可以通过单引号或者双引号来引入:

    var s1 = 'Single quotes work well for string literals.';
    var s2 = "Double quotes work just as well.";
    var s3 = 'It\'s easy to escape the string delimiter.';
    var s4 = "It's even easier to use the other delimiter.";
    

    字符串拼接可以通过 + 或者 换行 来实现,如:

    var a = '123' + '456'
    var b = '123'
        '456';
    assert(a == b)
    print(a);
    // Out: 123456
    

    另外,可以通过三重引号来修饰多行字符串(维持特定格式):

    var s1 = '''
    You can create
    multi-line strings like this one.
    ''';
    
    var s2 = """This is also a
    multi-line string.""";
    

    布尔类型

    Dart 中的 bool 类型可以通过 if-else 或者是 assert 来检查,如:

    // Check for an empty string.
    var fullName = '';
    assert(fullName.isEmpty);
    
    // Check for zero.
    var hitPoints = 0;
    assert(hitPoints <= 0);
    
    // Check for null.
    var unicorn;
    assert(unicorn == null);
    
    // Check for NaN.
    var iMeantToDoThis = 0 / 0;
    assert(iMeantToDoThis.isNaN);
    

    数组类型

    在 Dart 语言中,数组即列表,列表即数组。

    void main() {
      var list = [1, 2, 3];
      list.add(4);
      list.remove(3);
      list[1] = 5;
      var last = list[list.length - 1];
      print('list is $list');
      print('last is $last');
    }
    

    另外,你可以通过 或者 ...?(避免空异常) 来批量插入多个元素:

    var list1 = [1, 2, 3];
    var list2 = [0, ...list1];
    
    var list3;
    var list24 = [0, ...?list3];
    

    除此以外,还可以通过 if 或者 for 条件运算符来插入元素:

    var nav = [
      'Home',
      'Furniture',
      'Plants',
      if (promoActive) 'Outlet'
    ];
    
    var listOfInts = [1, 2, 3];
    var listOfStrings = [
      '#0',
      for (var i in listOfInts) '#$i'
    ];
    assert(listOfStrings[1] == '#1');
    

    Set 和 Map

    Dart中的Set是无序的唯一项的集合。要创建一个空集合,有以下两种方式:

    var names = <String>{};
    Set<String> names = {}; // This works, too.
    // var names = {}; // Creates a map, not a set.
    

    通过以下方式创建常量 Set:

    final constantSet = const {
      'fluorine',
      'chlorine',
      'bromine',
      'iodine',
      'astatine',
    };
    // constantSet.add('helium'); // Uncommenting this causes an error.
    

    至于 Map 存储的是键值对数据,keyvalue 可以是任何类型。可以通过以下方式创建一个 Map:

    var gifts = Map();
    gifts['first'] = 'partridge';
    gifts['second'] = 'turtledoves';
    gifts['fifth'] = 'golden rings';
    
    // 或者通过以下方式
    var gifts = {
      // Key:    Value
      'first': 'partridge',
      'second': 'turtledoves',
      'fifth': 'golden rings'
    };
    

    函数

    Dart 是一门完全面向对象的语言,即使它的函数也是一个对象,并且有自己的类型—— Function。这就意味着函数可以被赋值为一个变量,或者作为一个参数在其他函数之间传递

    对于只包含一个表达式的方法体,你也可以使用 => 的简写形式,如:

    void say() {
        print('123');
    }
    
    // 该写法与以上有同样效果
    void say2() => print('123');
    

    此外,函数同样支持类型推断,如:

    bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
    
    // 与下面的效果一样
    isNoble(atomicNumber) => _nobleGases[atomicNumber] != null;
    

    可选参数

    与 kotlin 语言类似,Dart 的 函数同样支持可选参数这一功能,主要分为命名可选参数位置可选参数,它们不能在一个函数中同时使用。但它们都支持默认参数设置

    • 命名可选参数

      命名可选参数通过花括号 {} 来指定可选的命名参数,如:

      void main() {
        hello(name: 'Tom');
      }
      
      void hello({@required String name='Jack', int age=18}) {
        print('Hello, my name is $name, i\'m $age years old.');
      }
      

      我们可以为命名可选参数设置默认值,在使用的时候如果不指定该可选参数的值,那么它就会自动使用默认值。另外,我们可以通过 @required 来标注那些不想被忽略的参数。

    • 位置可选参数

      顾名思义,可选位置参数就允许我们在使用某个函数时可以忽略某个参数,如:

      void main() {
        sayHello('Tom', 19);
      }
      
      void sayHello(String name, int age, [String hobby = null]) {
      	var result = 'Hello, my name is $name, i\'m $age years old';
      	if (hobby != null) {
      		result += ', my bobby is $hobby.';
      	}
      	print(result);
      }
      

    匿名函数

    不管什么语言,好像都能看到匿名函数的身影,我们可以通过以下方式来简单声明一个匿名函数:

    var loge = (msg) => Logger.print(Logger.Error, msg);
    
    void main() {
      loge("there has some errors");
    }
    

    Dart 中 list 就提供了匿名函数 —— forEach,如:

    var list = ['apples', 'bananas', 'oranges'];
    list.forEach((item) {
      print('${list.indexOf(item)}: $item');
    });
    

    常用操作符

    Dart 提供了很多功能强大的操作符,这里列举几个常用的:

    • 类型判断

      如:is 相当于 Java 中的 instanceof

    • 整除

      如:a ~/ b 等价于 (a /b) as int

    • 非空调用

      如:a?.b 相当于 a == null ? null : a.b

    • 三目运算

      如:a??b 相当于 a == null ? b : a

    • 三目赋值运算

      如:a ??= b 相当于 a = a == null ? b : a

    • 类型转换

      如:a as int 相当于 Java 中的 (int) a

    • 级联操作符

      级联操作符用**..** 来表示,主要用来对一个对象进行连续操作,有点类似 kotlin 中的 apply 和 let,如:

      var button = Button(this);
      button.text = 'Confirm';
      button.color = Color.parse("#f3f355");
      button.onClick.listen((v) => toast('Confirmed'));
      
      // 等价于下面写法
      Button(this) 
        ..text = 'Confirm' // Use its members.
        ..color = Color.parse("#f3f355")
        ..onClick.listen((v) => toast('Confirmed'));
      

    异常处理

    抛异常

    在 Dart 中可以抛出非空对象(不仅仅是 ExceptionError)作为异常。抛出异常的方式很简单,只需要这样:

    throw FormatException('Expected at least 1 section');
    
    throw 'Out of llamas!';
    
    void distanceTo(Point other) => throw UnimplementedError();
    

    捕获异常

    我们可以通过 try-on 来捕获某个特定异常,如:

    try {
      breedMoreLlamas();
    } on OutOfLlamasException {
      buyMoreLlamas();
    }
    

    当然,你可以抛出多个类型的 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 语句,那么异常将会在finally代码块之后传递。
        print('Catch Exception: $e');
      } finally {
        print('Close');
      }
    

    类和对象

    Dart 中,所有的对象都是类的实例,并且所有的类都是 Object 的子类。

    类的定义和构造函数

    类的定义用 class 关键字,如果未显式定义构造函数,会默认一个空的构造函数,这一点与 Java 不谋而合。另外,Dart 还提供 命名构造函数这一功能,格式为:Class.costructorName(var params)。这种用法在某些场景下很实用,比如:

    class Person{
      String name;
      int age;
      bool sex;
      String hobby;
    
      Person(this.name, this.age, this.sex, this.hobby);
    
      /// 命名构造函数
      Person.fromJson(Map json){
        print("Person constructor...");
        this.name  = json['name'];
        this.age   = json['age'];
        this.sex   = json['sex'];
        this.hobby = json['hobby'];
      }
    }
    

    通过命名构造函数,我就可以直接通过多种方式来生成当前类的实例,这里通过 Json 格式数据生成 Person 对象。另外,如果构造函数只是简单的参数传递,也可以直接在构造函数后加 : 来对参数进行赋值,多个参数可通过 , 相连:

    class Point {
        num x;
        num y;
        num z;
        
        Point(this.x, this.y, z) { //第一个值传递给this.x,第二个值传递给this.y
                this.z = z;
        }
        
        Point.fromeList(var list): //命名构造函数,格式为Class.name(var param)
                x = list[0], y = list[1], z = list[2]{//使用冒号初始化变量
        }
    
        //当然,上面句你也可以简写为:
        //Point.fromeList(var list): this(list[0], list[1], list[2]);
    
         String toString() => 'x:$x  y:$y  z:$z';
    }
    
    

    如果你要创建一个不可变的对象,你可以定义编译时常量对象
    需要在构造函数前加 const

    class ImmutablePoint {
        final num x;
        final num y;
        const ImmutablePoint(this.x, this.y); // 常量构造函数
        static final ImmutablePoint origin = const ImmutablePoint(0, 0); // 创建一个常量对象不能用new,要用const
    }
    

    属性访问器

    即我们常说的 Setter/Getter,主要是用来读写一个属性的方法。每个字段都对应一个隐式的 GetterSetter,但是调用的时候是 obj.name,而不是 obj.name()。当然,你可以通过 getset 关键字扩展功能
    来实现自己的 Setter/Getter , 如果字段为 final 或者 const 的话,那么它只能有一个 getter 方法。如:

    class Rectangle {
      num left, top, width, height;
    
      Rectangle(this.left, this.top, this.width, this.height);
    
      // Define two calculated properties: right and bottom.
      num get right => left + width;
      set right(num value) => left = value - width;
      num get bottom => top + height;
      set bottom(num value) => top = value - height;
    }
    
    void main() {
      var rect = Rectangle(3, 4, 20, 15);
      assert(rect.left == 3);
      rect.right = 12;
      assert(rect.left == -8);
    }
    

    工厂构造函数

    并不是任何时候我们都需要创建一个新的对象,如:可以返回一个已经缓存好的对象或者该类的子类对象。我们以返回该类的一个缓存对象为例:

    class Logger {
      final String name;
      bool mute = false;
    
      // _cache is library-private, thanks to
      // the _ in front of its name.
      static final Map<String, Logger> _cache =
          <String, Logger>{};
    
      factory Logger(String name) {
        return _cache.putIfAbsent(
            name, () => Logger._internal(name));
      }
    
      Logger._internal(this.name);
    
      void log(String msg) {
        if (!mute) print(msg);
      }
    }
    

    注意:factory 构造函数不能通过 this 关键字来获取类的成员。

    抽象类

    Dart 中并没有 interface 关键字,只有 abstract 来修饰"抽象类",但是,这里的抽象类既可以被继承(extends),也可以被实现(implements)。如:

    abstract class Person {  // 可以不用 abstract 修饰,如果加上 abstract 的话 Person 不能被实例化 
        String greet(who);   
    }
    
    class Student implements Person { 
        String name; 
        Student(this.name); 
         
        String greet(who) => 'Student: I am $name!'; 
    } 
    
    class Teacher implements Person { 
        String name; 
        Teacher(this.name); 
       
        String greet(who) => 'Teacher: I am $name!'; 
    } 
    
    void main() { 
        Person student = new Student('Wang'); 
        Person teacher = new Teacher('Lee'); 
        
        print( student.greet('Chen')); 
        print(teacher.greet('Chen')); 
    }
    

    同样地,Dart 中的类是单继承,多实现。这里使用的 implements 后,子类 Student 无法去访问父类 Persion 中的变量,但是抽象方法必须显式实现。相反,如果使用 extends 继承,子类就可以直接使用父类的非私有变量,倘若父类不是抽象类,那么子类同样不需要显式实现里面方法。如:

    // A person. The implicit interface contains greet().
    class Person {
      // In the interface, but visible only in this library.
      final _name;
    
      // Not in the interface, since this is a constructor.
      Person(this._name);
    
      // In the interface.
      String greet(String who) => 'Hello, $who. I am $_name.';
    }
    
    // An implementation of the Person interface.
    class Impostor implements Person {
      get _name => '';
    
      String greet(String who) => 'Hi $who. Do you know who I am?';
    }
    
    String greetBob(Person person) => person.greet('Bob');
    
    void main() {
      print(greetBob(Person('Kathy')));
      print(greetBob(Impostor()));
    }
    

    运算符重载

    以下的运算符支持重载功能:

    < + | []
    > / ^ []=
    <= ~/ & ~
    >= * << ==
    % >>

    这一点与 kotlin 语言中的运算符重载功能类似。我们以下面这个表示平面向量的类为例,为它增加两个向量相加和相减功能:

    class Vector {
      final int x, y;
    
      Vector(this.x, this.y);
    
      Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
      Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
    
      // Operator == and hashCode not shown. For details, see note below.
      // ···
    }
    
    void main() {
      final v = Vector(2, 3);
      final w = Vector(2, 2);
    
      assert(v + w == Vector(4, 5));
      assert(v - w == Vector(0, 1));
    }
    

    枚举

    枚举的使用比较简单,和 Java 中的用法类似,声明的元素 index 值从 0 开始计算。

    enum Color { red, green, blue }
    ......
    assert(Color.red.index == 0);
    assert(Color.green.index == 1);
    assert(Color.blue.index == 2);
    

    Mixin 混合模式

    Mixins 是一种在多个类的层级中复用类中代码的一种方式。在类名后添加 with 关键字,并在 with 后紧跟类的标识符列表,通过逗号分隔,如:

    class Maestro extends Person
        with Musical, Aggressive, Demented {
      Maestro(String maestroName) {
        name = maestroName;
        canConduct = true;
      }
    }
    

    如果想要声明一个混合模式,可以通过 mixin 来代替 class 定义一个不含构造方法的类:

    mixin Musical {
      bool canPlayPiano = false;
      bool canCompose = false;
      bool canConduct = false;
    
      void entertainMe() {
        if (canPlayPiano) {
          print('Playing piano');
        } else if (canConduct) {
          print('Waving hands');
        } else {
          print('Humming to self');
        }
      }
    }
    

    当然,我们也可以指定某个类来使用定义的混合模式,通过 on 关键字:

    mixin MusicalPerformer on Musician {
      // ···
    }
    

    静态变量和函数

    定义静态变量和函数的方法与 Java 类似:

    class Point {
      num x, y;
      Point(this.x, this.y);
      static const originalPoint = Point(0, 0);
    
      static num distanceBetween(Point a, Point b) {
        var dx = a.x - b.x;
        var dy = a.y - b.y;
        return sqrt(dx * dx + dy * dy);
      }
    }
    
    // usage
    void main() {
      var a = Point(2, 2);
      var b = Point(4, 4);
      var distance = Point.distanceBetween(a, b);
      assert(2.8 < distance && distance < 2.9);
      print(distance);
    }
    

    异步操作

    Dart 是单线程执行的,如果进行 I/O 操作或进行耗时的操作时,程序可能会发生阻塞。Dart 库中的很多函数都返回 Future 或者 Stream 对象,这些方法都是异步执行的,它们可以在建立一个耗时操作之后返回,而无需等待耗时操作执行完成。

    我们可以通过两种方式来实现异步操作:

    • 通过 asyncawait 实现
    • 借助于 Future API 来实现

    async 和 await

    通过 asyncawait 关键字,我们可以轻松实现异步操作。要使用 await,必须要将函数用 async 修饰,同时函数会返回一个 Future 对象。简单用法如下:

    Future checkVersion() async {
      try {
        version = await lookUpVersion();
      } catch (e) {
        // React to inability to look up the version
      }
    }
    

    生成器

    • 同步生成器 — sync*

      值得注意的是,同步生成器会返回 Iterable 对象:

      Iterable<int> naturalsTo(int n) sync* {
        int k = 0;
        while (k < n) yield k++;
      }
      
    • 异步生成器 — async*

      异步生成器返回 Stream 对象:

      Stream<int> asynchronousNaturalsTo(int n) async* {
        int k = 0;
        while (k < n) yield k++;
      }
      
    • yield*

      通过 yield* 在递归中提升性能:

      Iterable<int> naturalsDownFrom(int n) sync* {
        if (n > 0) {
          yield n;
          yield* naturalsDownFrom(n - 1);
        }
      }
      

    将类对象作为函数调用

    Dart 允许我们将一个类的对象作为函数来调用,只需要实现 call() 函数即可:

    class WannabeFunction {
      call(String a, String b, String c) => '$a $b $c!';
    }
    
    main() {
      var wf = new WannabeFunction();
      var out = wf("Hi","there,","gang");
      print('$out');
    }
    

    未完待续

    此文只是 Dart 征程的一个起点,亦是 Flutter 中的一块基石,后续还有更多进阶用法和细节 API 等着我们去挖掘,keep learning!

    展开全文
  • Dart编程语言.pdf(高清版)。 本书共9章,前6章是基础,后3章是进阶进行了深入的讲解,本书内容较为深入,不适合初学者,最好接触过其他编程语言。
  • Dart基础教学

    2019-06-13 10:38:46
    本课程主要采取图文与代码讲解的形式,充分帮助学员理解Dart原理与加深对代码的认知力度。 在讲解代码的基础上也会稍带部分设计模式与代码编程技巧等知识,让学员在学习代码的同时更能掌握实际中的编程技巧。
  • Dart 基础教程(一)

    千次阅读 2018-12-07 19:55:45
    dart 基础笔记 dart基础 void main(){ print('li'); var a = 1;//可以多次赋予 print(a); final b = -2;//变量只能赋值一次 print(b); const c = 3;//常量也不能修改 int d = 4;//整型 print(d.isEven);...

    dart 基础笔记

    dart基础

    void main(){
      print('li');
      var a = 1;//可以多次赋予
      print(a);
      final b = -2;//变量只能赋值一次
      print(b);
      const c = 3;//常量也不能修改
    
      int d = 4;//整型
      print(d.isEven);// 是否偶数 返回true
      print(d.isOdd);// 是否奇数 返回false
      print(b.abs());//取绝对值
    
      double e = 5.6;//浮点型 ~/这个是取整 %取余数
      print(e.round());//四舍五入
      print(e.floor());//不大于的最大整数
      print(e.ceil());//不小于的最小整数
      print(e.toInt());//change to int
      print(e.toDouble());//like his name
    
      //插值 这里一个很像format 或者是 %s
      print("d + b is ${d+b}");
      print('b is $b');//如果只是传一个参数就不用花括号了
    
      //string a = 'aaa';也可以使用3引号,多行。字符串前面加r 转义。
      //常用属性 length isEmpty isNotEmpty
      String ss = 'hhh123666666999999';
      print(ss.length);
      print(ss.isEmpty);
    
      //contains()是否包含,返回布尔值 索引indexOf() 大小写toLowerCase() toUpperCase()
      //trim()截取前后空格split()分隔 substring()截取。相当与python[0:4]
      print(ss.contains('hh'));
      print(ss.substring(0,4));
    
      //list ,const 不可变list,add()增加元素,insert(插入下标,元素) remove() clear()
      // sort() indexOf()返回位置 length长度属性 sublist()截取
      // shuffle()打乱 forEach()传入一个方法
      var list1 = const [1,2,3, 'ddd'];
      print(list1.sublist(0,2));
      list1.forEach(print);//循环这个list 调用这个方法
    
      //字典,.key .value containsKey() containsValue()
      var doc = {"h1":"here", "h2":"you", "h3":"are"};
      print(doc.keys);
      print(doc.values);
      print(doc.containsKey('hi'));//true
      
    }
    

    list

    list.asMap()//转list为字典 key为0,1,2...

    //dynamic 动态类型 可以被赋予不同的值

    ++ --

    a = 1;

    print(a++)//先打印后加1

    print(++a)//先加1再打印

    ??=

    ??= 赋值,上图中 b??=10的意思是如果b有值,那么b仍然是那个它原本该有的值,如果b没有值,那么b将会被赋予=之后的值。


    条件表达式

    三目运算符

    //条件表达式
    // 三目运算符condition?expr1:expr2
    // ??运算符expr1 ?? expr2
    void main(){
      int a = 1;
      String s = a == 1 ? "aaa" : "bbb";
      print(s);//aaa //a == 1 ? 如果是true 
                     //返回expr1 反之返回 expr2
    
    
      String z;
      String b = "java";
      var c = z ?? b;
      print(c);//java 如果两个那个值中有一个没有定义的话 返回另外一个,
               // 如果都定义了的话,返回第一个。如果都没有定义的话 返回 null
    }
    

    if

    //条件表达式
    // if
    void main(){
      int a = 1;
      if(a > 0){
        print('1111');
      }else if(a == 0){
        print(-111);
      }else {
        print(000);
      }
    }
    
    

    循环

    for循环

    for

    void main() {
      var list1 = [1,2,3,4,5,6,7,8,9,10];
      for(int index = 0; index < list1.length; index ++){//初始条件 操作,index++也可以写在花括号里
        print(list1[index]);//输出1到10
      }
    }
    

    for in

    void main(){
      var list = [1,2,3];
      for (var item in list){
        if(item != 2){
          print(item);//1 3
        }
      }
    }
    
    //1 2 3 4
    

    while循环

    while

    void main() {
      int a = 0;
      while(a < 5){
        print(a++);
      }
    }
    
    //1 2 3 4
    

    do... while...

    void main(){
      var b = 1;
      do{
        print(b++);
      }while(b > 0 && b < 5);
    }
    
    //1 2 3 4
    

    break 和 continue

    break 终止循环

    void main(){
      var list = [1,2,3];
      for (var item in list){
        if(item == 3){
          break;
        }
        print(item);
      }
    }
    
    // 1 2
    

    提一下assert

    如果布尔条件为false,则使用assert语句来中断正常执行。

    void main() {
      var a = 1;
      assert(a != 3);
      print(a);//1
    }
    
    void main() {
      var a = 1;
      assert(a != 1);
      print(a);//没有执行
    }
    

    continue 跳出当前循环 继续循环

    void main(){
      var list = [1,2,3,4,5,6];
      for (var item in list){
        if(item == 2){
          continue;
        }
        print(item);
      }
    }
    
    //1 3 4 5 6 
    

    switch...case语句

    var command = 'OPEN';
    switch (command) {
      case 'CLOSED':
        executeClosed();
        break;
      case 'PENDING':
        executePending();
        break;
      case 'APPROVED':
        executeApproved();
        break;
      case 'DENIED':
        executeDenied();
        break;
      case 'OPEN':
        executeOpen();
        break;
      default://默认情况
        executeUnknown();
    }
    

    与标签调用 标签可以自定义 test

    展开全文
  • dart语法

    千次阅读 2019-06-29 17:09:44
    重温dart语法 文章目录@[toc]入门dddd 入门 1、入口方法两种定义方式 main(){ print('你好dart'); } //加void表示方法没有返回值 void main(){ print('你好dart'); } dddd ...
  • Dart_02

    2020-11-13 10:55:40
    Dart_02类和对象类的定义构造方法普通构造方法命名构造方法利用命名构造方法,提供更加发方便的插件对象方式dyname和object初始化列表 类和对象 类的定义 Dart是一个面向对象的语言,面向对象中非常重要的概念就是...
  • dart安装(一)

    2020-06-03 21:35:01
    1.0 安装 ...brew tap dart-lang/dart brew install dart 安装包安装 链接:https://pan.baidu.com/s/1-CHNGkjzWN6T_GugFkMnoA 提取码:kvkf 2.0 编码提示 这里以vscode为例 搜dart,安装插件即可
  • 首先是下载adb. ...提取码:12wq 手机要打开开发者模式,不会百度(USB连接) 然后就是下载到c盘,把路径添加到环境变量中 如果不添加就会报错,如 成功的是这样的  在cmd中输入查询命令,就可以查到当前连接的手机...
  • Dart 的使用(基础)

    2020-11-21 17:47:04
    Dart 的使用 https://juejin.im/post/5d7a36ac6fb9a06ad5474b50 掘金 codeWhy 知识点总结 安装配置 1.使用Dart 语言 首先需要配置Dart环境,那么我们就需要下载 dart SDK ,然后找到bin文件夹路径,配置到环境变量...
  • 深入理解Google Flutter编程之Dart语言

    千次阅读 2018-09-12 18:53:35
    Flutter使用Dart语言开发。本篇整体介绍一下Dart语言。 上一篇Android Studio使用Google Flutter完整教程中SDK和插件以及环境变量的配置都很详细了。 如下截图是Dart语言SDK下载地址。对于Android开发,我们仅用到...
  • dart语言程序设计

    2013-10-22 05:59:37
    这是一本讲述Dart语言程序设计的英文书,Dart语言将是javascript 络结语言。速度快效率高。
  • 用Flutter开发Android App和iOS App需要使用Dart语言,所以本系列文章会深入介绍Dart语言的相关知识,后续还会推出Flutter App开发的系列文章,敬请期待...
  • Dart语言 基础– main()函数 不论在Dart还是Flutter中,必须都需要一个顶层的main()函数,它是整个应用的入口函数,main()函数的返回值是void,还有一个可选的参数,参数类型是List。 main() { } 1 基本数据类型 ...
  • Dart语言——45分钟快速入门(下)

    千次阅读 多人点赞 2019-03-23 00:38:17
    类和对象 类的定义 // Dart中定义一个类 class Person { String name; int age; Person(String name, int age) { ...Dart中的类与Java中的相似,不同的是,Dart中没有private、public这些成员访问修饰符...
  • flutter-Dart语言简介

    2019-03-14 15:35:52
    Dart语言简介 在之前我们已经介绍过Dart语言的相关特性,读者可以翻看一下,如果你熟悉Dart语法,可以跳过本节,如果你还不了解Dart,不用担心,按照笔者经验,如果你有过其他编程语言经验,尤其是Java和JavaScript...
  • 配置环境和"hello world" demo 前面已经配置...其实flutter sdk已经包含了dart sdk,其在fluuter的bin/cache目前下,名叫dart-sdk,在dart-sdk目录下也有一个bin目录,这个bin目录中就有一个dart命令命令,将dart-sd...
  • Dart语言的前世今生

    2019-12-27 15:30:50
    Dart语言将是您必须掌握的一门语言,因为他将是成为统一前端与后端的全栈语言。各位程序员朋友可要小心了,现在三个岗位的工作,未来可能只需要一个人了。 一、该不该学习Dart语言? 如果你在2018年问这个问题,...
  • Dart语言入门(一)

    千次阅读 2019-07-08 20:10:50
    最近好长时间没有写博客,也不知道要写点什么,一直也静不下心来学习,想看会学习视频,手机又放不下,看一会就去玩手机了。最近好不容易下定决心学习一波,...Dart诞生于2011年10月10日,是一种“结构化的Web编程”...
  • 文章内容是我学习时的点滴笔记,如有不好的地方,欢迎指出。 1 变量 1.1 变量声明 var、dynamic、Object ①未初始化变量声明: 声明未初始化的变量是可以改变得。 void main() { var data;... Ob...
  • 作为重新认识新语言的常规套路,每个程序员都不可避免的需要经历Hello World的历练,今天学习Dart语言也不例外,所以我们先来用Dart语言,输出Hello World: void main(){ print("Hello Wo...
  • Dart语言和Flutter基础

    千次阅读 2018-08-20 09:48:19
    前言  在如今的 Fultter 大潮下,本系列是让你看完会安心的文章。本系列将完整讲述:如何快速从0开发一个完整的 Flutter APP,... 系列文章分为三篇,第一部分是基础篇(针对Dart语言和Flutter基础),第二部分...
  • Dart语言基础

    2019-10-31 22:25:41
    Dart是Google公司推出的编程语言,于2011年就已经亮相了。Dart也是一门面向对象的语言,语法和Java,C,JavaScript很像。所以会Java语言,学习Dart一般会快一些。Dart里所有的类都可以看成是对象,是单继承,动态类...
  • 想学Flutter,就请关注这个专栏 Flutter系列(一)——详细介绍 Flutter系列(二)——与React ...Dart语言详解(一)——详细介绍 Dart语言详解(二)——基本语法 文档归档: https://github.com/yang0range/fl...
  • Flutter学习之Dart语言基础(关键字)

    千次阅读 2019-03-10 01:37:08
    Flutter日渐火爆,因此在进行Flutter学习前先学习一些其所使用的开发语言dart的基础,这篇文章主要学习了 Dart的基础代码示例 Dart的概念 Dart的关键字 Dart的基础代码示例 // 定义一个方法。 ...
  • 安卓,ios开发,flutter从入门到实战pdf。简单易学易操作。
  • 防采集标记:亢少军老师的课程和资料 ...Dart关键字 关键字 - - - abstract do import super as dynamic in switch assert else interface sync* e...
  • 1.Dart中任何一个可以用变量引用的都是一个对象,在 Dart 中 甚至连 数字、方法...Dart语言中的Object类 class Object { /** * Creates a new [Object] instance. * * [Object] instances have no meaningful s...
  • Flutter实战(二) 了解Dart语言

    万次阅读 2018-05-04 10:40:25
    在上一篇教程中说了Flutter使用Dart语言开发。本篇教程整体介绍一下Dart语言,注意,本篇不会介绍Dart具体语法细节,也不会介绍Dart VM、dart2js,因为这些和Flutter无关。本文会从Flutter开发角度来介绍Dart语言...

空空如也

1 2 3 4 5 ... 20
收藏数 37,056
精华内容 14,822
关键字:

dart