Dart

作者: Louis_King | 来源:发表于2019-03-20 09:16 被阅读0次

    概念(core concepts)

    1. dart:一切皆对象,所有对象都是继承自Object类。所有变量声明语句的默认值为 “null”。
    2. 类型声明:定义变量时需要声明变量的类型,并且不能在后续程序中给变量赋予其它类型的值。
    3. 泛型:可以指定容器内容可装载的数据类型,例如:List<int> 只能添加 int 类型的值,如需容纳所有类型可以使用 List<dynamic> 泛型。
    4. 全局函数:全局函数和普通函数一样,但可被任何模块访问。Dart 需要 main全局函数 作为程序运行的入口,main函数支static, async await。
    5. 全局变量:Dart 同样支持全局变量,定义与 main 前面,可被内部其余模块直接访问。
    6. 变量命名:以 “” 或 字母开头,后面可跟数字。以 “” 开头的变量意味着局部可访问。
    7. 打印函数:print 打印输出结果,类似JS的 console.log。
    8. 注释:“//” 单行注释,“/../” 多行注释,“///” 文档注释
    9. 异常:警告级别不会中断程序运行,错误级别将中断程序运行。

    内建变量(Variable)

    1. numbers 数值类型
      int:整数类型,取值范围:-2^63 ~ 2^63 - 1,不支持小数点。
      double:浮点数,64 位长度的浮点类型,小数点前面占16位。
      num:int 和 double 的基类,支持基本运算符“+”,“-”,“*”,“/”。int 类型还支持位运算符 “>>”,“<<”,“|”,“&” 。
      常用API:abs,ceil,floor 。
    2. strings
      String: utf-16编码字符串,可用单引号或双引号字面量,内部支持 访问变量,以及{} 执行表达式。字符串可直接多个字符串拼接,多行字符串可使用 '''str''' 。常用API:contains,startsWith,endsWith,indexOf,substring,split,toUpperCase,toLowerCase,trim,replaceAll。
      StringBuffer:字符串缓存区,通过 write、writeAll 写入数据,仅当调用 toString 时才生成字符串。
      RegExp:正则表达式,通过 hasMatch,allMatches 校验字符串,实例化时可使用Runes字符串( '\d+' => r'\d+' )。字符串查询相关API也支持正则匹配。
    3. booleans
      bool:布尔类型变量只支持 true、false 值。条件分支 “if-else” 只支持bool值判断,如果非bool值,则抛出异常。
    4. lists
      List: 列表,泛型变量 List<int>,泛型字面量 <int>[1,2]。指定泛型后,后续添加的元素均不能为其它类型变量、字面量。
    5. sets
      Set:不允许重复元素的集合,泛型变量 Set<int>,泛型字面量 <int>{1,2}。目前不支持泛型字面量,只能使用泛型变量进行元素类型限制。常用API:add,addAll,contains,containsAll。
    6. maps
      Map:kv字典,泛型变量 Map<String,int>,泛型字面量<String,int>{'str': 2}。key和value可为任何类型对象,key不可以重复。常用API: keys,values,containsKey,containsValue,remove,update。
    7. runes
      Runes:utf-32编码字符串,两字节固定编码,用于支持表情图编码字符集。字符编码
    8. symbols
      Symbol:不可变更标识符,字面量 #symbol,为编译时常量,即使压缩丑化代码也不会被变更。相同字符的标识符相等。

    函数(Function)

    1. Dart 是面向对象编程语言,函数也属于 Object 类型。
    2. 函数声明:支持 声明 或 不声明 函数返回值类型,匿名函数由声明的变量类型指定函数返回类型。如果函数体仅包含单行表达式,可简写为:bool isTest(int number) => number === 10;
    3. 可选参数:可选参数跟在必填参数后面,可指定其 位置 或 名称。如:
    // optional named parameters function
    bool namedParams({ bool test }) => test;
    namedParams(test: true);
    // optional positional parameters function
    bool positionalParams(bool test, [ bool optional ]) => test && optional;
    positionalParams(true);
    // set default value of optional params(default to null)
    void defaultValue({ bool value = true }) => value;
    
    1. main函数:main函数作为应用的入口函数,返回void,并通过 List<String> 获取命令行参数。
    2. 匿名函数:([ [type] params [, ...] ]) { codeBlock };
    3. 作用域:函数内部的环境变量只能被函数内部访问,函数外部无法访问。
    4. 闭包:函数引用了外部作用域,并在将来有可能会被调用。

    类(Classes)

    1. 类定义:类定义只能在 main 函数外部,main 内部不识别 class 关键词。
    2. 成员变量:用于描述类的属性,类中定义的 成员变量 可被每个实例对象访问。成员变量 支持 getter 和 setter,系统默认会为 成员变量 创建 getter,non-final变量 还会默认创建 setter 。定义 成员变量 时可进行赋值操作,该操作将会先于任何构造函数执行,若不进行赋值操作,默认为 null。( final变量初始化必须先于构造函数 )
    class Person {
      final String name; // “_” 表示私有变量,但实际运行中可被外部访问。
      Person(String name): this.name = name {} // 简写 Person(this.name);
    }
    
    1. 构造函数:
      默认构造函数:与类同名的构造函数,类定义若不包含默认构造函数,将使用不带参数的系统默认构造函数。如果为继承类,将无参调起调起父类构造函数。
      命名构造函数:在类名后面追加一个标识符,一般用于支持多种类型传参实例化。
      转移构造函数:仅对参数进行简单处理,然后通过其余构造函数完成对象实例化。
    class Person{
      String name;
      // 默认构造函数,变量初始化在所有构造函数之前完成
      Person(this.name);
      // 命名构造函数,通过 fromJson 说明类支持 Json 参数进行实例化
      Person.fromJson(Map<String, String> data): name = data['name'] {}
      // 转移构造函数,在姓名前面添加 ID,然后通过默认构造函数完成实例化
      Person.nameWithID(String name): this('ID_${name}');
    }
    

    常量构造函数:若实例对象不会有变更操作,可把类实例化作为编译时常量,多个常量对象之间相互等价。含有常量构造函数的类,所有 成员变量 必须为 final 变量。(不能通过 this 访问实例对象)

    class ImmutablePerson {
      final String name; // final 变量
      const ImmutablePerson(this.name); // 返回常量值,不包含函数体
      static final ImmutablePerson man = const ImmutablePerson('man'); // 静态属性
    }
    

    工厂构造函数:默认构造函数前加上 “factory” 关键字,实例化时可指定返回对象,可能为类的实例化对象、或 其它对象。(不能通过 this 访问实例对象)

    class Test {
      final String name;
      static Map<String, Test> _cache = <String, Test>{};
      factory Test(String name) {
        if (_cache.containsKey(name)) {
          return _cache[name];
        } else {
          _cache[name] = Test._internal(name); // 构造实例并缓存
          return _cache[name];
        }
      }
      Test._internal(this.name); // 最终构造函数
    }
    

    调用父类非默认构造函数:若父类没有使用默认构造函数(匿名、无参),则子类必须手动调用父类的构造函数,并传递相应的参数。

    class Person {
      final String name;
      Person.fromName(this.name); // 类定义了命名构造函数,默认构造函数失效
    }
    class Employee extends Person {
      final String job;
      // 父类构造函数的调用,必须位于初始化列表的最后面。
      Employee.fromNameAndJob(name, this.job): super.fromName(name) {}
    }
    
    1. 成员方法:用于描述类的行为、功能,类中定义的 成员方法 可被每个实例调用,但不同实例的方法因其所处作用域环境不同而不相等 assert(obj1.func !== obj2.func)。同时,Dart 成员函数还支持 getter,setter,和 abstract methods 。
    abstract class Rectangle {
      num top, left, width, height;
      Rectangle(this.top, this.left, this.width, this.height);
      // getter 方法,作为实例对象的属性
      num get right => left + width;
      num get bottom => top + height;
      // setter 方法,实例属性 right 支持赋值操作
      set right(num value) => left = value - width;
      set bottom (num value) => top = value - height;
      // 成员方法,可被实例直接调用(覆盖父类 Object 成员函数)
      String toString() {
        return '($top, $left, $bottom, $right)';
      }
      // 抽象方法,仅抽象类方可定义抽象方法,抽象函数的具体实现由其它类实现
      String abstractFunction();
    }
    class Test extends Rectangle {
      Test(top, left, width, height): super(top, left, width, height) {}
      String abstractFunction() {
        return 'This is a Abstract Function Test';
      }
    }
    
    1. 抽象类:自身无法进行实例化,仅对类进行抽象的描述,通常是对 成员方法 进行抽象描述,并由 派生类 完成方法的具体实现。
    abstract class AbstractContainer {
      void abstractMethod(); // 抽象方法没有函数体
    }
    
    1. 接口:描述一个类定义所必须要实现的 成员变量 和 成员方法,每个类定义隐式的创建了相应的 接口,其它类通过 implements 引入接口定义,并需要提供接口定义的 变量 和 方法 的具体实现(支持多接口引入)
    class Person {
      final _name; // 接口暴露的 属性
      Person(this._name); // 构造函数不属于 接口类 的定义
      String greet(String who) => 'Hello, $who. I am $_name'; // 接口暴露的 方法
    }
    class Impostor implements Person {
      get _name => 'test'; // 实现 Person._name 定义
      // 实现 Person.greet 定义,函数的参数和返回值必须与接口一致
      String greet(String who) => 'Hi $who. Do you know who I am?'; 
    }
    
    1. 继承:继承父类所有的 成员变量 和 成员方法,并可在 派生类 中被重写,也支持 noSuchMethod、操作符 的重写。Dart 支持单继承,但可以使用 Mixin 方式实现类定义代码的复用。
    class Test {
      final String memVariable; // 成员变量
      Test(this.memVariable); // 构造函数,将先于 派生类 构造函数的调用
      String memMethod() => memVariable; // 成员方法
    }
    class TestExt extends Test {
      TestExt(String variable): super(variable) {} // 父类构造函数先被调用
      @override
      String memMethod() => 'override'; // 重写父类的 memMethod 方法
      // 重写 noSuchMethod
      @override  // 访问类不存在的属性或方法时的处理,
      void noSuchMethod(Invocation invocation) {
        print('non-existent member: ${invocation.memberName}');
      }
      // 重写 “+” 操作符定义
      TestExt operator +(TestExt other) => TestExt(this.memVariable + other.memVariable)
    }
    
    1. 获取实例运行时类型:obj.runtimeType即可获取 obj 属于什么类的实例对象。

    特殊操作符

    1. 类型检测
      is:A is B, A是否继承自,或就是 B 对象(is!)。
      as:A as B,把A当B来调用,A 必须为继承自 B,或实现 B 接口定义的类。
    2. null 处理
      “?.”: 如果对象不包含指定属性,返回 null。
      “??”: 如果右边值为 null,返回左边值。
      “??=”: 如果变量当前为 null,则进行重新赋值。
    3. 链式调用(级联符)
    querySelector('#confirm') // Get an object.
      ..text = 'Confirm' // Use its' members.
      ..classes.add('important')
      ..onClick.listen((e) => window.alert('Confirmed!'));
    

    异常

    1. 异常 Exception
      抛出异常如果不被捕获并进行处理,将导致程序终止运行。可继承Exception实现自定义异常。
    2. 抛出异常 throw
      支持多种类型异常抛出,包括字符串类型、对象字面量等等。
    3. 重新抛出异常 rethrow
      直接把当前的异常重新抛出,不需要重新定义异常。
    4. 捕获异常 catch
      捕获异常,并对不同类型异常进行相应处理,阻止程序因为异常的冒泡而终止。
    5. 最终运行语块 finally
      无论程序是否产生异常、异常是否被捕获处理,都会进入 finally 程序。
    try {
      breedMoreLlamas();
    } on OutOfLlamasException {
      // A specific exception,and omit "e" param
      buyMoreLlamas();
    } on Exception catch (e) {
      // Anything else that is an exception
      print('Unknown exception: $e');
    } catch (e,s) { // "s" is stack trace
      // No specified type, handles all
      print('Something really unknown: $e');
    }
    

    特殊声明

    1. types declaration
      var:定义变量时不指定变量类型,若初始化时进行了赋值,则隐式声明变量类型,后续不能赋予其它类型的值;若初始化时不进行赋值,则后续可以赋予任何类型的值。
      dynamic: 指定变量为动态类型,后续可以赋予任何类型的值。
      Object:指定变量为 Object 类型,由于dart中所有值都是对象,而且对象都继承自Object,因此 Object 类型的变量可以容纳任何类型的值。
    2. final & const (omit types declaration)
      final:定义变量时必须初始化,并且不允许被重复赋值,但如果以 List 等复杂类型初始化,可通过 List API 改变其内部的值。类定义中使用 final 定义属性值时,属性的初始化必须在构造函数运行前完成。
    final x;
    Point.fromJson(Map<String, num> json) : x = json['x'] { ... }
    

    const:编译时常量,必须以 “字面量”,“常量”,或 它们的运算表达式 进行赋值,并且不可变更,即使使用 List 等复杂类型,也不允许调用其 API 变更内部的值。类定义中使用 static const 定义静态常量。

    仓库管理: package Manager

    pub是dart项目中依赖包管理器,类似node项目的npm。pub通过分析pubspec.yaml分析项目的依赖,并默认从 pub.dartlang.org 中拉去相应的依赖到本地。但是,如果没有翻墙,拉去会一直失败。

    相关文章

      网友评论

          本文标题:Dart

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