zoukankan      html  css  js  c++  java
  • 【dart 学习】 构造函数

    dart 构造函数
    
    ClassName(...) //普通构造函数
    
    普通构造函数
    这就是我们普通的构造函数,其样子和其它语言几乎一样
    
    class Point {
      num x, y;
    
      Point(num x, num y) {
        // There's a better way to do this, stay tuned.
        this.x = x;
        this.y = y;
      }
    }
    上例中只有两个成员变量,如果有10个,岂不是麻烦死?所以Dart有语法糖给你哦:
    
    class Point {
      num x, y;
    
      // Syntactic sugar for setting x and y
      // before the constructor body runs.
      Point(this.x, this.y);
    }
    它可以将x,y的赋值变得简单一些,就不用写构造函数的方法体了,记得括号后用分号哦。
    
    
    Classname.identifier(...) //命名构造函数
    
     命名构造函数
    
    class Point {
      num x, y;
    
      Point(this.x, this.y);
    
      // 命名构造函数,新增代码
      Point.origin() {
        x = 0;
        y = 0;
      }
    }
    
    请记住,命名构造函数不可继承,如果子类想要有 和父类一样的命名构造函数,那就写个同名的(通常也会在子类的命名构造函数里,调用父类的同名命名构造函数)
    
    
    const ClassName(...) //常量构造函数
    
    常量构造函数总结如下几点:
    
    常量构造函数需以const关键字修饰
    const构造函数必须用于成员变量都是final的类
    构建常量实例必须使用定义的常量构造函数
    如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
    下面结合实例,对以上几点加以说明
    
     
    
    正确的常量构造函数定义
    根据以上的总结,定义一个Point类,包含一个常量构造函数,注意其成员变量都是final类型,且构造函数用const修饰
    
    class Point {
      final int x;
      final int y;
      const Point(this.x, this.y);
    }
    常量构造函数需以const关键字修饰
    如下代码定义一个const对象,但是调用的构造方法不是const修饰的,则会报The constructor being called isn't a const constructor.错误
    
    void main() {
      const point = Point(1, 2); // 报错
    }
     
    class Point {
      final int x;
      final int y;
      Point(this.x, this.y);
    }
    const构造函数必须用于成员变量都是final的类
    如下代码中成员变量x为非final,会报Can't define a const constructor for a class with non-final fields.错误
    
    class Point {
      int x;
      final int y;
      const Point(this.x, this.y);
    }
     
    
    构建常量实例必须使用定义的常量构造函数
    如下代码,定义一个const对象,但是调用的却是非常量构造函数,会报The constructor being called isn't a const constructor.错误
    
    void main() {
      var point = const Point(1, 2); // 报错
      print(point.toString());
    }
     
    class Point {
      int x;
      int y;
      Point(this.x, this.y); // 非const构造函数
      
      String toString() {
        return 'Point(${x}, ${y})';
      }
    }
     
    
    如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
    如下代码,用常量构造函数构造一个对象,但是未用const修饰,那么该对象就不是const常量,其值可以再改变
    
    void main() {
      var point = Point(1, 2); // 调用常量构造函数,但是未定义成常量
      print(point.toString());
      point = Point(10, 20); // 可以重新赋值,说明定义的变量为非常量
      print(point.toString());
    }
     
    class Point {
      final int x;
      final int y;
      const Point(this.x, this.y);
      
      String toString() {
        return 'Point(${x}, ${y})';
      }
    }
     
    
    factroy ClassName(...) //工厂构造函数
    
    工厂构造函数的定义
    工厂构造函数是一种构造函数,与普通构造函数不同,工厂函数不会自动生成实例,而是通过代码来决定返回的实例对象.
    
    工厂构造函数的关键字为factory,下面我们用工厂构造函数写一个只能创造一个实例的类.
    
    class A{
      String name;
    
      static A cache;
    
      factory A([String name='A']){
        if(A.cache===null){
          A.cache=new A.newObject(name);
        }
        return A.cache;
      }
    
      A.newObject(this.name);
    }
    
    void main(){
      A a=new A('HelloWorld');
      print(a.name);
    
      A b=new A('HelloDart');
      print(b.name);
    
      print(a===b);
    }
    A类具有一个名为cache的静态成员,它将缓存A类的第一个实例.
    
    在工厂构造函数A中,首先判断A.cache是否已经存在实例(即判断是否是第一次实例化),如果存在则返回缓存的实例,不存在则新建一个实例并缓存.
    
    A.newObject是一个命名构造函数,用于创建实例.
    
    运行这段代码,会输出
    
    HelloWorld
    HelloWorld
    true
    其中字符串”HelloWorld”是第一个实例的name成员,在声明变量b时改用了”HelloDart”,但返回的实例的name成员仍然是”HelloWorld”.
    
    再用===运算符判断一下它们是否属于同一个对象,结果为true,变量a和b指向的是同一个对象.
    
    3.8.2 工厂构造函数的特性
    工厂构造函数类似于static静态成员,无法访问this指针,所以在工厂构造函数中能处理的任务较为有限.
    
    使用工厂构造函数时往往需要定义一个命名构造函数用来生产实例.
    
    注意点
    
    初始化列表
    初始化列表的执行顺序,在整个构造函数的最前面,它除了可以调用父类的构造函数,还可以在构造函数方法体之前,初始化一些成员变量。
    
    // Initializer list sets instance variables before
    // the constructor body runs.
    Point.fromJson(Map<String, num> json)
        : x = json['x'],
          y = json['y'] {
      print('In Point.fromJson(): ($x, $y)');
    }
    尤其是初始化那些final修饰的成员变量时,初始化列表很有用,因为在方法体中,不能给final修饰的成员变量赋值,因为在执行方法体的时候,final修饰的成员变量已经不能变了。这个地方很多人犯错。
    
    import 'dart:math';
    
    class Point {
      final num x;
      final num y;
      final num distanceFromOrigin;
    
      Point(x, y)
          : x = x,
            y = y,
            distanceFromOrigin = sqrt(x * x + y * y);
    }
    
    main() {
      var p = new Point(2, 3);
      print(p.distanceFromOrigin);
    }
    
    参考:
    链接:https://www.jianshu.com/p/a0ba5f2ac5ce
  • 相关阅读:
    [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
    HDU4607(求树中的最长链)
    java从文件中读取数据然后插入到数据库表中
    rcp(插件开发)插件B需要引用插件A中的jar包-如何处理依赖关系
    HDU 2084 数塔
    Object-c学习之路二(oc内存管理黄金法则1)
    android adb命令 unable to connect to 192.168.1.155:5555
    安装node.js / npm / express / KMC
    oracle断电重启之ORA-00600[4194]
    virtualbox虚拟机迁移出现"connot find device eth0"错误
  • 原文地址:https://www.cnblogs.com/mamamia/p/13679526.html
Copyright © 2011-2022 走看看