dart_darts - CSDN
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分钟快速入门(上)

    万次阅读 多人点赞 2020-09-24 23:43:28
    文章目录环境准备安装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基础教学

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

    千次阅读 2019-02-21 14:06:23
    变量 基本类型 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语言程序设计

    2020-07-25 23:33:09
    这是一本讲述Dart语言程序设计的英文书,Dart语言将是javascript 络结语言。速度快效率高。
  • Dart之旅

    2019-03-12 23:51:02
    Google出了个Flutter,像ReactNative一样,可以编写移动应用程序,于是决定学习一波,看了一天Dart官网的文档,决定写一篇博客加强记忆,这篇博文就是自己对官网文档的一个翻译。 文章目录基本的Dart程序重要概念...

    最近看见同学都这么努力,而我每天就是上班撸码,下班玩游戏,感觉自己也应该努力一点,做为一个大龄程序员,为了不必淘汰,必须要加强学习。Google出了个Flutter,像ReactNative一样,可以编写移动应用程序,于是决定学习一波,看了一天Dart官网的文档,决定写一篇博客加强记忆,这篇博文就是自己对官网文档的一个翻译。

    基本的Dart程序

    一个基本的Dart程序如下所示:

    从以上代码,我们可以知道以下几点:

    • Dart的入口也是main函数,写法和C/C++类似,但是可以省略返回值,返回值由最后的返回类型进行推导。
    • Dart使用var关键字定义变量,可以省略变量类型
    • 在字符串中可以使用$变量名或${变量名}来引用该变量

    重要概念

    • 一切能赋给一个变量的值都是一个对象,而每一个对象都是一个类的实例,不管是数值,函数,或者是null对象,所有对象继承自Object类
    • 尽管Dart是一种强类型语言,但是类型声明是可选的,Dart语言可以自动推导变量类型,如果你的确想声明这个变量无类型,请使用dynamic
    • Dart也支持泛型,如List或者List等
    • Dart支持顶级的函数,如main函数,也有类函数和实例函数,还有嵌套函数
    • 同样的,Dart也支持顶层的变量,也支持类变量和实例变量,就像Objc中的@property
    • 不像C++或Java,Dart没有public, protected, private等关键字,如果一个函数以下划线(_)开头,那么这是一个私有函数
    • 变量同样可以使用下划线(_)开头,表示这是一个私有变量
    • Dart同样有表达式和变量声明,比如说三目运算符condition ? expr1 : expr2
    • Dart工具能够指示警告和错误两种问题,警告只是提醒你,你的代码可能无法正常工作,错误分成编译时错误和运行时错误,编译时错误会阻止程序运行,运行时错误则会出现异常。

    Dart的关键字

    Dart的关键字如下所示,共有60个

    其中:

    • 角标为1的是上下文关键字,只在特定的地方有意义,他们在其他地方都可以用做变量
    • 角标为2的是内建变量,他们可以在大多数地方被用做变量,但不能用于类或类型名称,或者在import声明
    • 角标为3的是较新的关键字,这些关键字在Dart 1.0之后用于支持异步,当一个函数被标记为async或async或sync时,你不能使用await或者yield作为变量名
      既然如此,还有个解决问题的更好的方法,就是不用任何关键字做变量名

    变量

    变量的声明方式如下:

    var name = 'Bob';
    

    变量以引用的形式存在,变量名’name‘是一个值为’Bob’的String类型的引用,但是你可以通过指定类型来修改,如果一个变量不仅仅指定一个类型,请指定类型为Object或dynamic,如下:

    dynamic name = 'Bob';
    

    另外还有一种显式声明的方法来定义变量,如下:

    String name = 'Bob';
    

    默认值

    未初始化的变量都会有一个初始化的值null,甚至是一个数值类型,因为在Dart中,就算是一个普通的数值类型,也是一个对象。

    Final/Const

    如果你不想去修改一个变量,请使用final或const来代替var,一个final变量只能被设置一次,一个const变量是一个编译时常量,final顶层变量或类变量将会在第一次使用时被初始化。

    内建类型

    Dart语言的内建类型如下所示:

    • numbers: int, double
    • stirngs:String 表示字符串,
    • booleans:bool 表示布尔值
    • lists:List 表示数组
    • sets:Set 集合
    • maps:Map 表示字典,键值对
    • runes: 用于描述Unicode字符串
    • symbols

    Strings

    1. UTF-16字符串,可以使用单引号或双引号定义
    2. 使用+号连接字符串,使用’’’(三个单引号)或"""(三个双引号)可定义多行字符串
    3. 可以使用toString方法,创建字符串,使用类型的parse方法可以解析字符串
    4. 可以使用r‘’或r""定义原生字符串,原生字符串中的不会存在转义

    List

    list也许是几乎所有语言中最常用的集合类型,在Dart中,数组使用List对象,定义如下,类似JavaScript

    var list = [1, 2, 3];
    

    List支持泛型,你可以使用List,这样,如果你在列表中加入一个非整型对象,则会得到一个错误。List索引从0开始,-1表示最后一个元素,你可以使用list.length方法获得数组的长度。

    Sets

    Dart中的一个set是一个无序惟一容器,set的定义方式如下:

    var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
    

    Set也支持泛型,上述定义也可以使用Set

    Maps

    map是一个关键键值对的集合,map的键值对可以是任何类型,每个key只能出现一次,但值可以出现任意多次,其定义方式如下:

    var gifts = {
        //Key:          Value:
        'first'     :     'partridge',
        'second'  :  'turtledoves',
        'fifth'     :    'golden rings'
        };
    

    同样的, Map也支持泛型,上述定义也可以使用Map<String, String>,另外,以上类型也可以使用new关键字创建,如new Map(),但Dart 2 中,new关键字可以省略。通过键可以获取到值,访问方式如下:

    var value = gifts['first'];
    

    同时,你也可以直接给对应的键赋值,使用length获取长度。

    Runes

    runes表示UTF-32字符,比如\u{1f600}代表emoji表情(?) 。String类也有一些方法使你可以获得rune信息,codeUnitAt和codeUnit属性返回一个16位编码单位,使用runes属性可以获得一个runes字符串。

    Symbols

    一个Symbol类型表示一个操作符或Dart程序中的一个标识符定义,你可能永远也不会使用symbols,但是对于按名称引用标识符的API来说,它们是有用的,因为缩小更改了标识符名称,而不是标识符符号。要想拿到一个标识符的symbol,只需要使用#号即可。

    Functions

    Dart是一门真正的面向对象的语言,所以即使是一个函数也有一个类型Function,这意味着一个函数可以被赋值或用做参数传递到另外一个函数,你也可以像调用函数一样调用一个类,类似C++中的 仿函数。函数的定义如下所示:

    bool isNoble(int atomicNumber) {
        return _nobleGases[atomicNumber] != null;
    }
    

    尽管Dart推荐为公用Api声明类型,但你确实可以省略类型,如下所示:

    isNoble(atomicNumber) {
       return _nobleGases[atomicNumber] != null;
    }
    

    对于那些仅包含一句表达式的函数来说,你甚至可以按如下写法:

    bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
    

    这种写法就是一个闭包或Lambda函数,你可以使用@required来标记一个参数,表示这个参数必须要传值。

    可选参数

    可选参数可能是位置型或者是命名型,但不能同时存在

    可选命名参数

    当你在调用一个方法时,你可以使用paramName:value的方式给指定的参数赋值。当你定义一个函数时,使用{param1, param2, …}的方式定义如下所示:

    enableFlags(bold : true, hidden : false);
    

    可选位置参数

    参数使用[]包裹即可被定义为一个位置参数,如下所示:

    String say(String from, String msg, [String device]) {
        var result = '$from says $msg';
        if(device != null) {
            result = '$result with a $device';
        }
        return result;
    }
    

    这样一来,在调用参数的时候,你可以根据需要传递两个或三个参数。

    参数默认值

    你的函数可以使用=来为位置参数和命名参数定义一个默认值,如果没有指定默认值,默认值为null。如下所示:

    void enableFlags({bool bold = false, bool hidden = false}){...}
    

    main()函数

    每一个app都必须有一个顶级的main函数,作为整个app的入口,main函数返回值为void,标准的C/C++都是返回int,main函数的参数列表可以为空,也可以是一个List类型的参数列表。

    匿名函数

    大多数函数都是命名函数,你也能创建一个匿名函数,你可以将匿名函数赋值给一个变量,比如说你可以将它添加到集合或者从中移除。一个匿名函数看起来和命名函数差不多,定义方法如下:

    ([[Type] param1[, ...]]) {
        codeBlock;
        };
    

    从上述定义可以看出,匿名函数,可以省略返回类型和参数。

    Opeartor

    Dart的操作符类型如下表所示,你可以像C++一样,重写操作符。

    数学运算符

    Dart的数学运算符如下表所示:

    Dart操作符和运算法与其他的语言几乎一模一样,~/是整除的意思,只返回一个整型,比如:

    5 ~/ 2 = 2
    

    类似于C++中的

    (int)(5 / 2)
    

    另外Dart也支持++, – 这些操作符。还有各种等于,不等于,大于,小于操作符。

    类型测试

    as: 用于类型转换,is 测试该实例是否是一个类的实例,is!与is结果相反。

    赋值操作符

    Dart中有一个赋值操作符??=,当要赋值的变量(左值)是null时,则赋值,否则保持原值。
    另外还有逻辑运算符,位移运算符,条件运算符等。其中条件运算符除了?:这个三目运算符之外,还有一个expr1 ?? expr2运算符,如果expr1不为null, 返回expr1的值,否则返回expr2的值

    级联运算

    级联(…)允许实现类型链式的调用方法,它让你额外的访问同一个类型的一些属性,如下所示:

    querySelector('#confir')
    ..text = 'Confirm'
    ..classes.add('important')
    ..onClick.listen((e)=>window.alert('Confirmed!'));
    

    以上代码可以分解为以下代码

    var button = querySelector('#confirm');
    button.text = 'Confirm';
    button.classes.add('import');
    button.onClick.listen((e) => window.alert('Confirmed!'));
    

    其他运算符

    Dart中有一个?.运算符,称做条件成员访问,例如foo?.bar,当foo为null的时候选择访问bar,否则选择访问foo。

    流程控制

    Dart中的流程控制和其他语言类似,共有如下几种

    • if and else
    • for循环
    • while 和 do-while 循环
    • break and continue
    • switch and case
    • assert

    其中,大部分的使用方法和C/C++一致,只有switch有区别,区别如下:

    1. dart中的case 语句必须以break结尾,否则会报错,但C/C++中并未有此规定
    2. 当且仅当一个case 为空时,可以继续往下执行,但C++中case可包含代码块,如下所示:

    Dart:

    var command = 'CLOSED';
    switch (command) {
      case 'CLOSED': // Empty case falls through.
      case 'NOW_CLOSED':
        // Runs for both CLOSED and NOW_CLOSED.
        executeNowClosed();
        break;
    }
    

    C++:

    int command = 0;
    switch(command) {
     case 0:
           printf("0");
     case 1:
           printf("1");
           break;
    }
    
    1. C++中的switch类型只能为整型,但是Dart中可以为任意类型
    2. 如果想实现C++的方法,可以使用continue label的方式,跳转到指定标签继续执行case

    异常

    Dart代码可以抛出和捕获异常,异常是一种指示一些意外情况发生的错误,如果异常没有捕获,那么抛出的异常可能导致程序挂起或终止。Dart提供Exception和Error两种类型,除了预定义的异常类型,你还可以定义自己的异常类型。然而Dart程序可以抛出任何非空对象,不仅仅是Exception或Error。

    Throw & Catch

    Dart使用throw关键字来抛出异常,在Java中,使用catch来捕获异常,但是在Dart中,则使用on关键字来捕获,使用cache来传递异常参数,单独的catch会捕获所有异常,代码如下所示:

    try {
      breedMoreLlamas();
    } on OutOfLlamasException {
      // A specific exception
      buyMoreLlamas();
    } on Exception catch (e) {
      // Anything else that is an exception
      print('Unknown exception: $e');
    } catch (e) {
      // No specified type, handles all
      print('Something really unknown: $e');
    }
    

    其中,catch不单只有一个异常参数,还有一个CallStack参数,表示程序的调用栈,类似于Java中的printStackTrace()方法。同时,你还可以使用rethrow关键字将正在处理的异常进行再抛出,由调用的函数继续捕获进行处理。

    Finally

    类似于Java中的finally,不管最后发生何种异常,finally中的代码都会执行。

    Classes

    Dart 是一门面向对象语言,每个对象都是一个类的实例,而每一个类都是由Object类扩展下来,除了Object之外,每个类都有一个父类。每个类也包含一个this,类似C++。

    访问类成员

    对象由成员和函数组成,当你调用一个方法时,该方法就可以访问该对象中的函数和数据。使用点(.)来访问成员变量或成员函数。使用?.来避免空指针异常。

    成员变量

    成员变量的定义如下:

    class Point {
      num x; // Declare instance variable x, initially null.
      num y; // Declare y, initially null.
      num z = 0; // Declare z, initially 0.
    }
    

    可以在里面进行初始化,如果未初始化,则默认初始化为null。所有的成员变量会生成一个隐式的getter方法,非final实例变量也会隐式生成一个setter方法。

    构造函数

    你可以通过构造函数来创建一个对象,构造函数通常以类名或类名.标识符命名,你还可以使用const 构造函数来创建一个const对象。在C++中,使用构造函数,如果不使用初始化列表,我们应该写如下代码:
    C++:

    Point(int x, int y) { this->x = x; this->y = y};
    

    但是在Dart中,你可以使用类似如上的写法,还有另外一种更简便的方法:

    Point(this.x, this.y);
    

    如果你不为当前类声明一个构造函数,Dart将为你提供一个默认的构造函数,默认的构造函数没有参数,并且会调用父类的无参构造方法,代码可编写如下:

    Point():super() {}
    

    初始化列表

    我们知道,在C++中,构造函数有一个初始化列表,如下所示:

    Point(int x, int y) : x(x), y(y) {}
    

    在Dart中,同样可以使用初始化列表,使用方法如下:

    Point(x, y) : x = x, y = y {}
    

    构造重定向

    有时候一个构造函数只有一个目的,就是重定向到该类的另一个构造函数中,重定义构造函数的函数体为空,定义如下:

    Point.alongXAxis(num x) : this(x, 0);
    

    常构造

    如果你产生的对象不会被修改,你可以使这些对象保持编译时常量,要这样做,定义一个const构造函数,确保所有变量为final类型。

    Factory构造函数

    通常情况下,构造函数会创建一个新的实例,但有时候你需要复用对象而不是创建新对象,则可以使用factor构造函数,如下代码所示:

    class Logger {
      final String name;
      bool mute = false;
      
      static final Map<String, Logger> _cache =
          <String, Logger>{};
    
      factory Logger(String name) {
        if (_cache.containsKey(name)) {
          return _cache[name];
        } else {
          final logger = Logger._internal(name);
          _cache[name] = logger;
          return logger;
        }
      }
    }
    

    Getter & Setter

    Getter和Setter指定用于读取和写入权限的方法,每个实例变量都会有一个隐式的getter方法,你可以通过实现自己的getter或setter创建额外的属性。如下所示:

    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);
    }
    

    对象类型

    要想获得一个对象的类型,可以使用对象的runtimeType属性,该属性返回一个Type对象,如下所示:

    print('The type of a is ${a.runtimeType}');
    

    抽象类

    在C++中,也有抽象类的概念,我们把包含有纯虚函数的类称做抽象类,并没有任何关键字标记,C++中的定义如下所示:

    class Test {
        virtual void test(void) = 0;
    };
    

    抽象类不能实例化,子类继承自抽象类,必须实现纯虚函数,否则该子类也不能实例化。在Dart中,使用abstract来定义一个抽象类。其中包含的方法是抽象函数,也必须在子类中实现。

    隐式接口

    每个类隐式的定义了一个接口,这个接口包含所有的实倒方法,如果你需要创建一个类B但不从A继承,可以使用implements关键字实现该接口,并实现其中的方法。

    继承与覆写

    和Java一样,Dart使用extends来继承一个类,如果需要覆盖父类的方法,需要使用@override,Dart也可以像C++一样重写操作符函数, 如下所示:

    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));
    }
    

    noSuchMethod()

    当检测或者尝试使用一个不存在的方法或变量时,你可以覆写noSuchMethod方法,否则将会抛出一个异常。如下所示:

    class A {
      // Unless you override noSuchMethod, using a
      // non-existent member results in a NoSuchMethodError.
      @override
      void noSuchMethod(Invocation invocation) {
        print('You tried to use a non-existent member: ' +
            '${invocation.memberName}');
      }
    }
    

    除了以下几种情况,否则你不能调用一个未实现的方法:

    • 接收者有一个dynamic的类型定义
    • 接收者有一个定义为未实现方法的类型,并且实现了不同于Object类中的noSuchMethod()方法

    枚举类型

    枚举类型是一个特别的类,通常用于表示一个固定的数值或常量。使用方式如下:

    enum Color { red, green, blue }
    

    每一个枚举类型都有一个称为index的getter方法,返回一个从0开始的对应的值在枚举中的索引。枚举类型可以在switch语句中使用,如果没有将所有的情况都处理完整,你将会得到一个警告。使用枚举类型还有如下限制:

    • 你不能继承,混入或实现一个枚举
    • 你不能显式的实例化一个枚举

    特征添加:混入

    混入是一种在多个类继承中重用类代码的方式,要想使用混入,在with关键字后添加一个或多个混入类名称,示例如下:

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

    要实现混入,创建一个继承自Object的没有构造函数的类,除非你想要你的混入用起来不像一个常规的类,使用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');
        }
      }
    }
    

    指定一个仅有确定类型

    import和library能帮助你创建一个模块并且分享出去,库不仅仅提供API,更是一个以下划线开头的可视类型。每一个Dart app都是一个库,即使并没有使用library指令。库可以以包的形式被使用。通常使用import来引用一个库中的命名空间。import惟一要求的参数就是一个指定库的URI,对于内建的库来说,你需要指定dart:,如果该库是由包管理器提供的,则应该使用package:。

    如果你引入了两个命名有冲突的库,你可以使用as关键字为其中一个或多个同时指定一个前缀,示例如下:

    import 'package:lib1/lib1.dart';
    import 'package:lib2/lib2.dart' as lib2;
    

    你也可以引用库中的一部分,使用show关键字,可以指定从库中仅引入某个类,使用hide则可以引用除该类中的其他类,如下所示:

    // Import only foo.
    import 'package:lib1/lib1.dart' show foo;
    
    // Import all names EXCEPT foo.
    import 'package:lib2/lib2.dart' hide foo;
    

    延迟加载允许应用在使用到一个库的时候进行加载,以下是一些你可能需要延迟加载的情况:

    • 需要减少app的初动速度
    • 执行A/B测试-尝试交替实现一个算法
    • 加载很少使用的功能,比如一个可选的屏幕和对话框

    要延迟加载一个库,你必须道先使用deferred as来引入一个库,之后在使用的时候调用loadLibrary()方法,如下所示:

    import 'package:greetings/hello.dart' deferred as hello;
    Future greet() async {
      await hello.loadLibrary();
      hello.printGreeting();
    }
    

    你可以多次调用loadLibrary(),但是这个类仅会被加载一次。使用延迟加载时,你必须要谨记以下几点:

    • 使用延迟加载的库中的常量引入时不再是常量。记住,这些常量在加载之前是不存在的。
    • 你不能使用导入文件中的类型,相反,考虑将接口类型移动到由延迟库和导入文件导入的库中。
    • Dart会在你使用deferred as定义的命名空间中隐藏的插入一个loadLibrary()调用,loadLibrary()返回一个Feature对象。

    异步支持

    Dart库是一个充满返回一个Feature或Stream方法的库。这些方法都是异步的,他们可能在设置某些耗时的操作之后就返回而不等待他们完成。async和await关键字支持异步编程,可以让你像编写同步代码一样的编写异步代码。

    处理Features

    当你需要使用完整的Feature时,你有两个选择:

    • 使用async 和 await
    • 使用Feature API,如从库中的引入

    使用async和await的代码是异步的,但是它看起来会像同步的代码一样。要使用await,代码必须在一个async方法中,使用try,catch,finally来处理错误和清理操作,如下所示:

    Future checkVersion() async {
      var version = await lookUpVersion();
      // Do something with version
    }
    

    在一个异步方法中,你可以多次使用await,在一个await表达式中,它的值通常是一个Feature,如果不是一个Feature,这个值也是一个原子值,Feature对象指定一个promise返回一个对象。await表达式的值就是这个返回的对象,await表达式会中断执行直接这个对象可以使用。如果你使用await的时候获得一个编译时错误,确保await是在async方法当中

    处理Streams

    当你需要从Stream中获取一个值,你有两个选择:

    • 使用async和一个异步循环(await for)
    • 使用Stream API

    如下所示:

    await for (varOrType identifier in expression) {}
    

    这个表达式的值是一个Stream,执行进程如下所示:

    • 等待直到Stream发射一个值
    • 执行for循环的body,变量设置为发射的值
    • 重复1和2直接到Stream关闭

    如果需要停止监听Stream,你可以使用break或return来中断循环。

    生成器

    当你需要延迟生成一个值的序列时,可以考虑使用一个生成器函数,Dart内建支持两类生成器

    • 同步生成器(Synchronous generator): 返回一个Iterable对象
    • 异步生成器(Asynchronous generator): 返回一个Stream对象

    要实现一个同步生成器函数,你需要使用sync*标记,然后使用yield语句传送该值。如下所示:

    Iterable<int> naturalsTo(int n) sync* {
      int k = 0;
      while (k < n) yield k++;
    }
    

    要实现异步生成器函数,你需要使用async*标记,然后使用yield语句传送该值,如下所示:

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

    如果你的生成器是一个递归函数,你可以使用yield*来提高性能。

    可调用类

    如果你要使你的类能像函数一样被调用,类似C++中的仿函数,请实现call()方法

    class WannabeFunction {
      call(String a, String b, String c) => '$a $b $c!';
    }
    

    Typedefs

    在Dart中,函数是一个对象,就像String和Number对象一样。一个typedef或者函数类型别名,为函数类型提供一个在声明字段和返回类型时可以使用的名称,当一个函数类型赋值给一个变量的时候,typedef会维持原有的类型信息。使用方法如下:

    typedef Compare = int Function(Object a, Object b);
    

    Metadata

    使用Metadata给你的代码添加额外的信息。一个Metadata标注以字符@开始,跟着是一个编译时常值,例如deprecated或者调用一个常量构造函数。有两个标注在所有Dart代码中都可以使用,@deprecated和@override。你可以定义自己的metadata标注,只需要类定义了const构造函数。如下所示:

    library todo;
    
    class Todo {
      final String who;
      final String what;
    
      const Todo(this.who, this.what);
    }
    

    使用方式如下:

    import 'todo.dart';
    
    @Todo('seth', 'make this do something')
    void doSomething() {
      print('do something');
    }
    

    Metadata可以出现在库、类、typedef、类型参数、构造函数、工厂、函数、字段、参数或变量声明之前,也可以出现在导入或导出指令之前。您可以使用反射在运行时检索元数据。

    注释

    Dart中的注释也分单行注释//和多行注释/**/, 其中还有一种文档注释类型,以/**或///开始,同样以**/或///结束。

    展开全文
  • Dart基础系统学习

    2019-07-01 18:04:23
    目录介绍 01.变量声明 1.1 var声明变量 1.2 变量和常量 1.3 dynamic和Object ...03.Dart函数和运算符 3.1 Dart函数介绍 3.2 命名参数 3.3 参数默认值 3.4 void无返回值 3.5 匿名函数 3.6 运算符介绍 04.D...

    目录介绍

    • 01.变量声明
      • 1.1 var声明变量
      • 1.2 变量和常量
      • 1.3 dynamic和Object
    • 02.数据类型
      • 2.1 基本数据类型
      • 2.2 String字符串
      • 2.3 List数组
      • 2.4 Map集合
    • 03.Dart函数和运算符
      • 3.1 Dart函数介绍
      • 3.2 命名参数
      • 3.3 参数默认值
      • 3.4 void无返回值
      • 3.5 匿名函数
      • 3.6 运算符介绍
    • 04.Dart流程控制
      • 4.1 流程控制语句
      • 4.2 if和else
      • 4.3 for循环
      • 4.4 while循环
      • 4.5 break和continue
      • 4.6 switch和case
      • 4.7 assert断言
    • 05.Dart面向对象
      • 5.1 类简单介绍
      • 5.2 构造函数
      • 5.3 继承类
      • 5.4 重载和重写
      • 5.5 抽象类
      • 5.6 访问权限
      • 5.7 静态方法
      • 5.8 泛型
    • 06.Dart异步解读
      • 6.1 Future简单介绍
        • 6.1.1 普通异步案例
        • 6.1.2 耗时异步案例
      • 6.2 async/await介绍
      • 6.3 看一个案例
    • 07.Dart异常捕获
      • 7.1 异常处理形式
      • 7.2 抛出异常
      • 7.3 捕获异常
      • 7.4 Finally讲解
    • 08.Dart枚举
      • 8.1 枚举使用
      • 8.2 元数据
      • 8.3 自定义注解
    • 09.Dart字符串
      • 9.1 String简单介绍
      • 9.2 单双引号互相嵌套
      • 9.3 字符串拼接方式

    想换个工作,渴望同行内推我

    • 个人信息
      • 姓名:杨充【26岁】
      • 邮箱:yangchong211@163.com
      • GitHub:https://github.com/yangchong211
      • 博客汇总:https://github.com/yangchong211/YCBlogs
      • 干活集中营:Android端技术博客和开源项目审核员
      • 目前工作情况:在职状态
      • 技术项目和博客:GitHub项目7k以上star,follower1.1k以上,发表博客100多篇。
      • 热爱技术:开源项目和博客多次被鸿洋,郭霖,Android技术周刊,干活集中营等等推荐。
      • 学历:武汉软件工程职业学院,大专学历
      • 工作年限:3年多
    • 关于近期投递简历一点感想
      • 从进入Android这个行业以来,前两次几乎都是朋友内推,面试机会相对容易,都是一个App一个人做或者两个人做,用户相对来说并不多。这次想着离职,主要是想进入一个较大的平台,大概可以理解为Android端有个至少四五人,可以进行技术交流,渴望自己能够在技术上突破,这就像自己平时独自跑步,和跟着一群跑马拉松的人跑步,那种紧张感肯定是不一样的。
      • 近段时间,尝试着向一些较大的公司投递简历,大概在拉钩上投了15个左右(不喜欢海投),发现绝大多数简历到不了技术那里,就被人事说学历不够,经验不够,工作不匹配等情况回绝。不过也可以理解,看简历无非就是学历和经验,貌似自己的履历是差了一点。
      • 这大概是第一次在网上发一个主动希望同行内推的介绍,如果你的公司有Android方面的招聘,能否内推一下我这个小人物,感谢。

    01.变量声明

    1.1 var声明变量

    • 类似于kotlin中的var,它可以接收任何类型的变量,但最大的不同是Dart中var变量一旦赋值,类型便会确定,则不能再改变其类型,如:
      var t;
      t="yc";
      // 下面代码在dart中会报错,因为变量t的类型已经确定为String,
      // 类型一旦确定后则不能再更改其类型。
      t=1000;
      
      • 最大的不同是Dart中var变量一旦赋值,类型便会确定,则不能再改变其类型。因为Dart本身是一个强类型语言,任何变量都是有确定类型的,在Dart中,当用var声明一个变量后,Dart在编译时会根据第一次赋值数据的类型来推断其类型,编译结束后其类型就已经被确定。
    • 思考一下,dart在编译时是如何确定数据的类型呢?

    1.2 变量和常量

    1.2.1 变量
    • 变量如下所示
      var curPage = 0;
      var title = "潇湘剑雨:小杨逗比";
      
    • Dart 不需要给变量设置 setter getter 方法, 这和 kotlin 等类似。Dart 中所有的基础类型、类等都继承 Object ,默认值是 NULL, 自带 getter 和 setter ,而如果是 final 或者 const 的话,那么它只有一个 getter 方法。
    1.2.2 常量
    • const 的值在编译期确定,final 的值要到编译时才确定。
      • Dart 中 final 表示常量
        //final 表示常量
        final title = "潇湘剑雨:小杨逗比";
        
      • static const 组合代表了静态常量
        //static const 组合代表了静态常量
        static const String complete = "COMPLETE";
        
    • final和const区别
      • 两者区别在于:const 变量是一个编译时常量,final变量在第一次使用时被初始化。被final或者const修饰的变量,并且变量类型可以省略。
    • 注意点
      • const变量同时也是final变量,实例变量可以为final但不能是const。
      • 编译错报错,原因final变量只能赋值一次!
      //定义初始化一个变量
      final double number = 13.14;
      number = 520;
      //调用打印数字方法
      printNumber(number);
      
    1.2.3 注意+
    • 在Java中可以直接通过 + 号将字符串和int类型拼接,但是在Dart中是不行的。
      //在Java中,下面操作可行
      ToastUtils.showRoundRectToast("二维码扫描"+1000);
      
      //在dart中,下面错误操作,编译不通过,直接会有红色提示
      int yc = 0;
      print("潇湘剑雨" + yc);
      
      //在dart中,下面正确操作
      int yc = 0;
      print("潇湘剑雨" + yc.toString());
      

    1.3 dynamic和Object

    • Object 是dart所有对象的根基类,也就是说所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象.
      • dynamicvar一样都是关键词,声明的变量可以赋值任意对象.而dynamicObject相同之处在于,他们声明的变量可以在后期改变赋值类型.
      dynamic t;
      Object x;
      t = "hi world";
      x = 'Hello Object';
      //下面代码没有问题
      t = 1000;
      x = 1000;
      
      • dynamicObject不同的是,dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用Object的属性与方法, 否则编译器会报错. 如:
       dynamic a;
       Object b;
       main() {
           a = "";
           b = "";
           printLengths();
       }   
      
       printLengths() {
           // no warning
           print(a.length);
           // warning:
           // The getter 'length' is not defined for the class 'Object'
           print(b.length);
       }
      
      • 变量a不会报错, 变量b编译器会报错
        • dynamic的这个特性与Objective-C中的id作用很像.
        • dynamic的这个特点使得我们在使用它是需要格外注意,这很容易引入一个运行时错误.

    02.数据类型

    2.1 基本数据类型

    • var 可以定义变量,同时 Dart 属于动态类型语言,支持闭包。
      • Dart 中 number 类型分为 int 和 double ,其中 java 中的 long 对应的也是 Dart 中的 int 类型。Dart 中没有 float 类型。
      //int类型   这里没有long类型
      var positionIndex = 0;
      
      //double类型   这里没有float类型
      var time = 1993.03;
      
      • 这里提个小建议,声明变量的时候,可以选择加上具体类型。添加类型可以更加清晰表达你的意图。
      //定义初始化一个变量
      double number = 13.14;
      
    • Dart 下只有 bool 型可以用于 if 等判断,不同于 JS 这种使用方式是不合法的 var g = “null”; if(g){} 。
      • 以bool代表布尔值,只有两个对象是布尔类型的,那就是true和false所创建的对象,这两个对象都是编译时常量。
      //类似Java中的布尔类型
      bool mIsLogin = false;
      
      if (!mIsLogin) {
        //没有登陆
        print('没有登陆');
      } else {
        //已经登陆
        Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
          return new CollectPage();
        }));
      }
      
      • 注意,下面这种情况会报错
      String name ="yc";
      //报错 因为name不是bool类型
      if(name){
        print(name);
      }
      
      • 可以使用的是先式的检查值。assert是语言内置的断言的函数,仅在检查模式有效,在开发过程中,除非条件为真,否则会引发异常。(断言失败则程序立刻终止)
      // 检查是否为空字符串
      var fullName = 'doubi';
      assert(fullName.isEmpty);
      
      // 检查是否小于等于0
      var hitPoints = 0;
      assert(hitPoints <= 0);
      
      // 检查是否为 null.
      var unicorn;
      assert(unicorn == null);
      
      // 检查是否为 NaN.
      var iMeantToDoThis = 0 / 0;
      assert(iMeantToDoThis.isNaN);
      

    2.2 String字符串

    • Dart 中,switch 支持 String 类型。后面会单独拿出来讲解一下。
      //字符串
      var title = "潇湘剑雨:小杨逗比";
      

    2.3 List数组

    • 声明一个list非常的简单,可以简单使用方括号[]定义list。下面是list的常用操作。
      main(List<String> args) {
        //或者
        List arr1 = [1,2,3,4];
        var arr2 = [1,2,3,4];
       
        print(list); //Output: [1, 2, 3, 4]
        //Length 长度
        print(list.length);
       
        //Selecting single value 获取单个值
        print(list[1]);    //Outout: 2
       
        //Adding a value 添加值到list
        list.add(10);
       
        //Removing a single isntance of value 删除单个值
        list.remove(3);
       
        //Remove at a particular position 删除指定位置的值
        list.removeAt(0);
      }
      
      • 注意:第一个元素索引是0,最后一个元素是length-1
    • 如果你想定义一个编译时常量list,例如,list的内容是不可改变的,可以使用关键字const
      var list = const [1,2,3,4];   
      

    2.4 Map集合

    • 定义map也很简单。可以使用花括号{}定义map。
        void test() {
          var map = {
            'key1': 'value1',
            'key2': 'value2',
            'key3': 'value3'
          };
          //Fetching the values 获取值
          print(map['key1']);    //Output: value1
          print(map['test']);    //Output: null
      
          //Add a new value 添加值
          map['key4'] = 'value4';
      
          //Length   获取长度
          print(map.length);
      
          //Check if a key is present 检查是否存在
          var containsKey = map.containsKey('value1');
          print(containsKey);
      
          var entries = map.entries;
          var values = map.values;
        }
      
      • 打印日志
      2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: value1
      2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: null
      2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: 4
      2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: false
      
    • 也可以使用map构造函数定义map。
      • 可以发现map可以存储多种类型的数据
      var squares = new Map();
      squares["a"] = 1;
      squares["b"] = 2;
      squares["c"] = 3.0;
      squares["d"] = [1,2];
      squares["e"] = "yc逗比";
      
      print(squares['a']);    
      print(squares['e']);
      
      • 打印日志
      2019-06-20 17:27:32.841 4281-4329/com.hwmc.auth I/flutter: 1
      2019-06-20 17:27:32.841 4281-4329/com.hwmc.auth I/flutter: yc逗比
      

    03.Dart函数和运算符

    3.1 Dart函数介绍

    • dart中的函数和JavaScript中有点类似。你需要定义就是函数的名字、返回值(有返回值或者void)、参数。
        void test(){
          var name = fullName('杨充', '逗比');
          print(name);
        }
      
        String fullName(String firstName, String lastName) {
          return "$firstName $lastName";
        }
      

    3.2 命名参数

    • dart有个叫命名参数的东西。当你调用函数的时候,你必须指定参数的名字。要使用命名参数,可以将函数的参数包括在花括号{}内。
      • 如果你在调用命名参数的函数时,没有指定参数的名字,则会提示红色报错,无法通过编译。
        void test(){
          var name = fullName('杨充', '逗比');
          print(name);
        }
      
        String fullName(String firstName, String lastName) {
          return "$firstName $lastName";
        }
      

    3.3 参数默认值

    • 你可以给函数的命名参数一个默认值。下面的例子给lastName一个默认值。
        void test(){
          var name = fullName('杨充', '逗比');
          print(name);
        }
      
        fullName(String firstName, String lastName) {
          return "$firstName $lastName";
        }
      

    3.4 void无返回值

    • 大多数都是void无返回值的函数,这个跟java中类似。没什么好讲的……

    3.5 匿名函数

    • 在dart中函数比较灵活,例如,你可以将函数当参数传递给另一个函数。
        void test(){
          out(printOutLoud);
        }
      
        out(void inner(String message)) {
          inner('Message from inner function');
        }
      
        printOutLoud(String message) {
          print(message.toUpperCase());
        }
      
      • 这里定义一个函数名字为out,需要一个函数参数。然后我定义一个名为printOutLoud的函数,他所做的就是将字符串以大写的形式打印。
      • dart 也有匿名函数,所以上面的例子中不用预定一个函数,而是传递一个匿名函数。
    • 另一个匿名函数的例子。
      
      

    3.6 运算符介绍

    • 这部分和java差不多,可以直接看我java部分的博客:运算符

    04.Dart流程控制

    4.1 Dart流程控制

    • 大概有这么多
      • if和else
      • for循环
      • while循环
      • break和continue
      • switch和case
      • assert断言

    4.2 if和else

    • if-else 和其他语言一样比较简单。
      var number = 57;
      if (number > 100) {
        print('Large Number');
      } else if (number < 100) {
        print('Small Number');
      } else {
        print('Number is 100');
      }
      
    • 可以用三元运算符代替if-else
      int age = 60;
      String status = age < 50 ? "年轻人" : "老年人";
      

    4.3 for循环

    • for循环和java几乎是一样的,代码如下
        void test() {
          for (int i = 0; i < 10; i++) {
            print('$i');
          }
        }
      

    4.4 while循环

    • while循环如下所示
        void test() {
          int i = 0;
          while(i < 10) {
            print('$i');
            i++;
          }
        }
      
    • The classic for do while loop. 典型的do while循环。
        void test() {
          int i = 0;
          do {
            print('$i');
            i++;
          } while (i < 10);
        }
      

    4.6 break和continue

    4.7 switch和case

    • 代码如下所示
        void test() {
          int age = 50;
          switch(age) {
            case 10:
              print('Too Young.');
              break;
            case 20:
            case 30:
              print('Still Young!');
              break;
            case 40:
              print('Getting old.');
              break;
            case 50:
              print('You are old!');
              break;
          }
        }
      

    05.Dart面向对象

    5.1 类简单介绍

    • 创建一个类和创建类的实例
      void test1(){
        Dog d = new Dog();
      }
      class Dog {
      
      }
      
      
      var cat = new Cat("逗比", 12);
      class Cat {
        String name;
        int age;
      
        Cat(String name, int age) {
          this.name = name;
          this.age = age;
        }
      }
      

    5.2 构造函数

    • 普通构造函数
      var cat = new Cat("逗比", 12);
      
      class Cat {
        String name;
        int age;
      
        Cat(String name, int age) {
          this.name = name;
          this.age = age;
        }
      }
      
    • 命名构造函数
      • 给构造函数提供了名称,这样做使得不同的构造函数变的更加清晰。
      Map map = new Map();
      map['name']= "哈巴狗";
      map['age'] = 5;
      Dog d = new Dog.newBorn(map);
      
      
      class Dog {
        String name;
        int age;
      
        Dog(this.name, this.age);
      
        Dog.newBorn(Map json) {
          name = json['name'];
          age = json['age'];
        }
      }
      

    5.3 继承类

    • 可以使用extends关键字继承其他的类。
      • Pug 类继承Dog类,通过super关键字调用Dog类的构造函数。
      Pug p = new Pug('逗比哈巴狗', 5);
      print(p.name);
      
      
      class Dog {
        String name;
        int age;
      
        Dog(this.name, this.age);
      
        Dog.newBorn() {
          name = 'Doggy';
          age = 0;
        }
      }
      
      class Pug extends Dog {
        Pug(String name, int age): super(name, age);
      }
      
    • 也可以通过this关键字,在冒号之后调用同一个类中的其他构造函数。
      • 定义了两个命名构造函数,他们只需要dog的名字,然后调用Pug的默认构造函数。
      Pug p = new Pug.small('傻逼');
      print(p.name);
      
      class Dog {
        String name;
        int age;
      
        Dog(this.name, this.age);
      
        Dog.newBorn() {
          name = '逗比哈巴狗';
          age = 0;
        }
      }
      
      class Pug extends Dog {
        Pug(String name, int age): super(name, age);
      
        Pug.small(String name): this(name, 1);
      
        Pug.large(String name): this(name, 3);
      }
      

    5.4 重载和重写

    • 方法重写
      • 代码如下,最后打印值是:你真是个逗比
      Pug p = new Pug();
      print(p.bark());
      
      class Dog {
        bark() {
          print('Bow Wow');
        }
      }
      
      class Pug extends Dog {
        @override
        bark() {
          print('你真是个逗比!');
        }
      }
      
    • 方法重载
      
      

    5.5 抽象类

    • 可以通过abstract关键字声明抽象类
      • 只需要在类声明前添加abstract关键字,方法不需要。方法只需要签名,不需要实现。
      abstract class AbstractDog {
        void eat();
        void _hiddenMethod();
      }
      
      class SmallDog extends AbstractDog{
        @override
        void _hiddenMethod() {
          
        }
      
        @override
        void eat() {
          
        }
      }
      

    5.6 访问权限

    • 默认类中的所有属性和方法是public的。在dart中,可以在属性和方法名前添加“_”使私有化。现在让我们使name属性私有化。
      • 可以发现,调用私有化变量或者方法的时候会出现红色警告
        void test() {
          Dog d = new Dog('哈巴狗', 5);
          //这个报错
          print(d.name);
          print(d.age);
        }
      
      • Dog代码如下所示
      class Dog {
        String _name;
        int age;
      
        Dog(this._name, this.age);
      
        String get respectedName {
          return 'Mr.$_name';
        }
      
        set respectedName(String newName) {
          _name = newName;
        }
      
        Dog.newBorn() {
          _name = '哈巴狗';
          age = 0;
        }
      
        bark() {
          print('Bow Wow');
        }
      
        _hiddenMethod() {
          print('I can only be called internally!');
        }
      }
      

    5.7 静态方法

    • 如果想让方法或者属性静态化,只需要在声明前添加static关键字。
      void test() {
        Dog.bark();
      }
      
      
      class Dog {
        static bark() {
          print('Bow Wow');
        }
      }
      

    5.8 泛型

    • dart全面支持泛型。假设你想在你定义的类中,想持有任意类型的数据。如下是怎样使用泛型定义这样的类。
      DataHolder<String> dataHolder = new DataHolder('Some data');
      print(dataHolder.getData());
      dataHolder.setData('New Data');
      print(dataHolder.getData());
      //下面这个会报错,因为dataHolder对象在创建的时候就已经限制为String类型
      dataHolder.setData(123);
      print(dataHolder.getData());
      
      
      class DataHolder<T> {
        T data;
      
        DataHolder(this.data);
      
        getData() {
          return data;
        }
      
        setData(data) {
          this.data = data;
        }
      }
      

    06.Dart异步解读

    6.1 Future简单介绍

    • async 库中有一个叫Future的东西。Future是基于观察者模式的。如果你熟悉Rx或者JavaScript的Promises,你就很容易明白了。
      • 首先先看一下下面的案例,看看它们之间有什么区别?
        void testA() async{
          new Future<String>(() {
            return "This is a doubi";
          });
        }
      
        Future testB() async{
          return new Future<String>(() {
            return "This is a doubi";
          });
        }
      
        Future<String> testC() {
          return new Future<String>(() {
            return "This is a doubi";
          });
        }
      
    6.1.1 普通异步案例
    • Future是支持泛型的,例如Future,通过T指定将来返回值的类型。
      • 定义了一个叫getTest的函数,返回值为Future.你可以通过new关键字创建一个Future。Future的构造函数,需要一个函数作为参数,这个函数返回T类型的数据。在匿名函数中的返回值就是Future的返回值。
      • 当调用了getTest方法,他返回Future.我们通过调用then方法订阅Future,在then中注册回调函数,当Future返回值时调用注册函数。同时注册了catchError方法处理在Future执行之间发生的异常。这个例子中不会发生异常。
        void test() {
          getTest().then((value) {
            print("测试----------"+value);
          }).catchError((error) {
            print('测试----------Error');
          });
        }
      
        Future<String> getTest() {
          return new Future<String>(() {
            return "This is a doubi";
          });
        }
        
        //打印结果
        2019-06-21 17:11:12.941 16501-16583/com.hwmc.auth I/flutter: 测试----------This is a doubi
      
      • 下面这个案例会发生异常
        void test() {
          getTest().then((value) {
            print("测试----------"+value);
          }).catchError((error) {
            print('测试----------Error');
          });
        }
      
        Future<String> getTest() {
          return new Future<String>(() {
            return "This is a doubi";
          });
        }
        
        //打印结果
        2019-06-21 17:18:46.896 16501-16583/com.hwmc.auth I/flutter: 测试----------Error
      
    6.1.2 耗时异步案例
    • 在生产环境中都是一些耗时的操作,例如,网络调用,我们可以使用Future.delayed()模仿。
      • 现在如果你运行,你将需要2秒,才能返回结果。
        void test() {
          getTest().then((value) {
            print("测试----------"+value);
          }).catchError((error) {
            print('测试----------Error');
          });
        }
      
        Future<String> getTest() {
          return new Future<String>.delayed(new Duration(milliseconds: 2000),() {
            return "This is a doubi";
          });
        }
      
      • 接下来再看一个案例。在调用函数之后,我们添加了print语句。在这种场景中,print语句会先执行,之后future的返回值才会打印。这是future的预期行为.但是如果我们希望在执行其他语句之前,先执行future。
        void test() {
          getTest().then((value) {
            print("测试----------"+value);
          }).catchError((error) {
            print('测试----------Error');
          });
          print('测试----------逗比是这个先执行吗');
        }
      
        Future<String> getTest() {
          return new Future<String>.delayed(new Duration(milliseconds: 2000),() {
            return "This is a doubi";
          });
        }
        
        2019-06-21 17:26:16.619 16501-16583/com.hwmc.auth I/flutter: 测试----------逗比是这个先执行吗
        2019-06-21 17:26:17.176 16501-16583/com.hwmc.auth I/flutter: 测试----------This is a doubi
      

    6.2 async/await介绍

    • 思考一下,看了上面的案例,对于future的预期行为,如果我们希望在执行其他语句之前,先执行future,该怎么操作呢?
      • 这就需要用到需要用到async/await。在test函数的花括号开始添加async关键字。我们添加await关键字在调用getTest方法之前,他所做的就是在future返回值之后,继续往下执行。我们将整个代码包裹在try-catch中,我们想捕获所有的异常,和之前使用catchError回调是一样。使用awiat关键字,必须给函数添加async关键字,否则没有效果。
      • 注意:要使用 await,其方法必须带有 async 关键字。可以使用 try, catch, 和 finally 来处理使用 await 的异常!
        Future test() async {
          try {
            String value = await getTest();
            print("测试----------"+value);
          } catch(e) {
            print('测试----------Error');
          }
          print('测试----------逗比是这个先执行吗');
        }
      
        Future<String> getTest() {
          return new Future<String>.delayed(new Duration(milliseconds: 2000),() {
            return "This is a doubi";
          });
        }
        
        2019-06-21 17:32:37.701 16501-16583/com.hwmc.auth I/flutter: 测试----------This is a doubi
        2019-06-21 17:32:37.702 16501-16583/com.hwmc.auth I/flutter: 测试----------逗比是这个先执行吗
      

    6.3 看一个案例

    • 一个 async 方法 是函数体被标记为 async 的方法。 虽然异步方法的执行可能需要一定时间,但是 异步方法立刻返回 - 在方法体还没执行之前就返回了。
      void getHttp async {
          // TODO ---
      }
      
      • 在一个方法上添加 async 关键字,则这个方法返回值为 Future。
        • 例如,下面是一个返回字符串的同步方法:
        String loadAppVersion() => "1.0.2"
        
      • 使用 async 关键字,则该方法返回一个 Future,并且 认为该函数是一个耗时的操作。
        Futre<String> loadAppVersion() async  => "1.0.2"
        
      • 注意,方法的函数体并不需要使用 Future API。 Dart 会自动在需要的时候创建 Future 对象。
    • 好的代码是这样的
      void main() {
       //调用异步方法
       doAsync();
      }
      
      // 在函数上声明了 async 表明这是一个异步方法
      Future<bool> doAsync() async {
        try {
          // 这里是一个模拟请求一个网络耗时操作
          var result = await getHttp();
          //请求出来的结果
          return printResult(result);
        } catch (e) {
          print(e);
          return false;
        }
      }
      //将请求出来的结果打印出来
      Future<bool> printResult(summary) {
        print(summary);
      }
      
      //开始模拟网络请求 等待 5 秒返回一个字符串
      getHttp() {
       return new Future.delayed(Duration(seconds: 5), () => "Request Succeeded");
      }
      
    • 不好的写法
      void main() {
       doAsync();
      }
      
      Future<String> doAsync() async {
          return  getHttp().then((r){
            return printResult(r);
          }).catchError((e){
            print(e);
          });
      }
      
      Future<String> printResult(summary) {
        print(summary);
      }
      
      Future<String> getHttp() {
       return new Future.delayed(Duration(seconds: 5), () => "Request Succeeded");
      }
      

    07.Dart异常捕获

    7.1 异常处理形式

    • dart 使用经典的try-catch处理异常,使用关键字throw抛出一个异常。

    7.2 抛出异常

    • 看看如何抛出异常
        void test1(){
          divide(10, 0);
        }
      
        divide(int a, int b) {
          if (b == 0) {
            throw new IntegerDivisionByZeroException();
          }
          return a / b;
        }
      
      • 当b变量的值为0的时候,抛出一个内置的异常IntegerDivisionByZeroException。
    • 如何定义异常日志呢?
      • 可以在异常中携带一个字符串信息。
        void test1(){
          divide(10, 0);
        }
      
        divide(int a, int b) {
          if (b == 0) {
            throw new Exception('逗比,不能为0的');
          }
          return a / b;
        }
      

    7.3 捕获异常

    • 某种类型的异常可以通过on关键字捕获,如下:
        void test1(){
          try {
            divide(10, 0);
          } on IntegerDivisionByZeroException {
            print('逗比,异常被捕获了');
          }
        }
      
        divide(int a, int b) {
          if (b == 0) {
            throw new IntegerDivisionByZeroException();
          }
          return a / b;
        }
      
    • 注意问题,捕获的异常层级要大于抛出的异常,否则捕获会失败
      • 还是会抛出异常’逗比,不能为0的’,因为Exception比IntegerDivisionByZeroException层级要高。
        void test1(){
          try {
            divide(10, 0);
          } on IntegerDivisionByZeroException {
            print('逗比,异常被捕获了');
          }
        }
      
        divide(int a, int b) {
          if (b == 0) {
            throw new Exception('逗比,不能为0的');
          }
          return a / b;
        }
      
    • 如果你不知道抛出异常的类型,或者不确定,可以使用catch块处理任意类型的异常。
        void test1(){
          try {
            divide(10, 0);
          } on IntegerDivisionByZeroException {
            print('逗比,异常被捕获了');
          } catch (e) {
            print(e);
          }
        }
      
        divide(int a, int b) {
          if (b == 0) {
            throw new Exception('yc other exception.');
          }
          return a / b;
        }
      

    7.4 Finally讲解

    • dart也提供了finally块,即是否发生异常这个块都会执行。
        void test1(){
          try {
            divide(10, 0);
          } on IntegerDivisionByZeroException {
            print('逗比,异常被捕获了');
          } catch (e) {
            print(e);
          }finally {
            print('I will always be executed!');
          }
        }
      
        divide(int a, int b) {
          if (b == 0) {
            throw new Exception('yc other exception.');
          }
          return a / b;
        }
      

    08.Dart枚举

    8.1 枚举使用

    • dart 支持枚举,用法和java一样。
      Dog d = new Dog('哈巴狗', 12, CurrentState.sleeping);
      print(d.state == CurrentState.sleeping); //Prints 'true'
      
      
      enum CurrentState {
        sleeping,
        barking,
        eating,
        walking
      }
      
      class Dog {
        String name;
        int age;
        CurrentState state;
      
        Dog(this.name, this.age, this.state);
      
        static bark() {
          print('Bow Wow');
        }
      }
      

    8.2 元数据

    • 使用元数据给代码添加额外信息,元数据注解是以@字符开头,后面是一个编译时常量或者调用一个常量构造函数。
    • 有三个注解所有的Dart代码都可使用:@deprecated、@override,@proxy,下面直接上@deprecated的示例:
    
    
    • 元数据可以在library、typedef、type parameter、constructor、factory、function、field、parameter、或者variable声明之前使用,也可以在import或者export指令之前使用,使用反射可以再运行时获取元数据信息。

    8.3 自定义注解

    • 定义自己的元数据注解。下面的示例定义一个带有两个参数的@toDo注解:
      void test1() {
        doSomething();
      }
      
      
      @toDo('seth', 'make this do something')
      void doSomething() {
        print('do something');
      }
      
      class toDo {
        final String who;
        final String what;
        const toDo(this.who, this.what);
      }
      

    09.Dart字符串

    9.1 String简单介绍

    • Dart字符串是UTF-16编码的字符序列,可以使用单引号或者双引号来创建字符串:
      String str1 = '单引号字符串';
      String str2 = "双引号字符串";
      
      print(str1);        //输出:单引号字符串
      print(str2);        //输出:双引号字符串
      

    9.2 单双引号互相嵌套

    • String中单、双引号互相嵌套情况如下所示
      String str1 = '单引号中的"双引号"字符串';
      String str2 = "双引号中的'单引号'字符串";
      
      print("yc-str1--" + str1);
      print("yc-str2--" + str2);
      
      //单引号里面有单引号,必须在前面加反斜杠
      String str3 = '单引号中的\'单引号\'';
      String str4 = "双引号里面有双引号,\"双引号\"";
      print("yc-str3--" + str3);
      print("yc-str4--" + str4);
      
      • 打印值
      2019-06-21 17:52:07.722 16501-16583/com.hwmc.auth I/flutter: yc-str1--单引号中的"双引号"字符串
      2019-06-21 17:52:07.723 16501-16583/com.hwmc.auth I/flutter: yc-str2--双引号中的'单引号'字符串
      2019-06-21 17:52:07.723 16501-16583/com.hwmc.auth I/flutter: yc-str3--单引号中的'单引号'
      2019-06-21 17:52:07.723 16501-16583/com.hwmc.auth I/flutter: yc-str4--双引号里面有双引号,"双引号"
      
    • 注意点::
      • 单引号嵌套单引号之间不允许出现空串(不是空格),双引号嵌套双引号之间不允许出现空串:
      //String str5 = '单引号''''单引号';  //报错了,逗比
      String str6 = '单引号'' ''单引号';
      String str7 = '单引号''*''单引号';
      String str8 = "双引号"" ""双引号";
      String str9 = "双引号""*""双引号";
      //String str10 = "双引号""""双引号";   //报错了,逗比
      print("yc-str6--" + str6);
      print("yc-str7--" + str7);
      print("yc-str8--" + str8);
      print("yc-str9--" + str9);
      
    • 打印值
      2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str6--单引号 单引号
      2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str7--单引号*单引号
      2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str8--双引号 双引号
      2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str9--双引号*双引号
      

    其他介绍

    01.关于博客汇总链接

    02.关于我的博客

    博客汇总项目开源地址:https://github.com/yangchong211/YCBlogs

    展开全文
  • dart语法

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

    千次阅读 多人点赞 2020-06-09 20:54:02
    类和对象 类的定义 // Dart中定义一个类 class Person { String name; int age; Person(String name, int age) { ...Dart中的类与Java中的相似,不同的是,Dart中没有private、public这些成员访问修饰符...
  • dart安装(一)

    2020-06-03 22:10:19
    1.0 安装 ...brew tap dart-lang/dart brew install dart 安装包安装 链接:https://pan.baidu.com/s/1-CHNGkjzWN6T_GugFkMnoA 提取码:kvkf 2.0 编码提示 这里以vscode为例 搜dart,安装插件即可
  • Dart

    2018-08-16 21:28:14
    Dart 事记 2018年8月8日,谷歌宣布推出 Dart 2 的第二个稳定版本。
  • Dart 调用C语言混合编程

    千次阅读 2019-05-17 21:07:29
    Dart 调用C语言 本篇博客研究Dart语言如何调用C语言代码混合编程,最后我们实现一个简单示例,在C语言中编写简单加解密函数,使用dart调用并传入字符串,返回加密结果,调用解密函数,恢复字符串内容。 环境准备 ...
  • Dart 虚拟机运行原理

    2020-09-22 11:51:08
    这篇文章将一起来了解 Dart 虚拟机的运行原理,Dart VM 是一种为 Dart 语言提供执行环境虚拟机。我们知道 Dart VM 既可以支持JIT(Just in time),边解释执行边编译的编译模式;同时也支持AOT(Ahead of time),...
  • Dart 和 Java 通信这块的知识点涵盖了 Dart&C 以及 Java&C 的通信,我们先有简单的业务组件的定义再到底层实现原理进行分,我们现在从Flutter定义的三种 Channel 中的 MethodChannel 使用进行剖析。 Dart和...
  • Dart 异步编程详解

    千次阅读 2020-06-09 20:55:11
    文章目录Dart 异步编程Dart 的事件循环调度任务延时任务Future 详解创建 Future注册回调async 和 awaitIsolatespawnUrispawn使用场景 Dart 异步编程 编程中的代码执行,通常分为同步与异步两种。简单说,同步就是...
  • Dart基础-类

    千次阅读 2015-07-02 11:58:47
    dart是面向对象的编程语言,每一个对象是一个类的实例,所有类都源于Object,创建一个对象,你可以使用 new 关键字构建一个类,构造函数的名字可以是 ClassName 或 ClassName.identifiervar jsonData = JSON....
  • 原文(节选):Announcing Dart 2.7: A safer, more expressive Dart 翻译:老黑牛 声明:侵权联删 Dart 2.7 添加了对扩展方法的支持,同时新增了一个处理特殊字符的包。在null安全方面我们也做了更新,并在DartPad...
  • Dart中的Isolate

    千次阅读 2019-11-05 12:30:39
    Dart中的Isolate Dart语言,是Google在2011年推出的Web开发语言,由Chrome浏览器V8引擎团队的Lars Bak主持,目的是要取代JavaScript称为下一代结构化Web开发语言。 不过由于NodeJs在兴起,让JavaScript拥有了服务端...
  • Dart 与 C 的互相调用

    2020-09-22 11:51:09
    从这篇文章开始将一起来研究 Dart 2.5 之后推出一个新的特性,就是 Dart 与 C(或 C++)的互操作。这就意味着在 Dart 可以做一些类似 JNI 操作。 Dart 与 C 的互操作主要是借助 dart:ffi 库,ffi 全称为 foreign ...
  • Dart-基础语法-更新

    千次阅读 2019-08-07 11:53:54
    Dart-基础语法 之前写过一篇基础语法, 后来读刘望舒的微信推文发现这篇总结的也挺全乎, 特别是环境搭建 ,关键字,异常捕获, 类的继承部分 作为学习参考吧, 转载过来,也方便以后查阅。 原文链接: ...
  • Dart学习之方法函数

    万次阅读 2019-09-19 09:44:56
    上一篇我们了解了Dart的基本语法,本篇我们学习Dart的函数。 先说下我学习Dart函数的感受吧,我尝试用java语言的形式去学习Dart,但是令我意外的是,我刚迈出第一步Dart就把我踢出门外。什么意思呢?比如说,在Java...
1 2 3 4 5 ... 20
收藏数 34,543
精华内容 13,817
关键字:

dart