Dart9.构造函数

本文深入探讨了Dart语言中的各种构造函数,包括普通构造函数、命名构造函数、重定向构造函数、超类构造函数、常量构造函数、工厂方法构造函数等。并通过具体示例展示了如何使用这些构造函数进行对象的创建和初始化。

class.dart

import 'dart:math';

main() {
  //普通构造函数
  var p = new Point(1, 1); //new 可省略 var point = Point(1, 2);
  print(p);  // 输出 Point(x = 1, y = 1)

  Point p1;
  print(p1.runtimeType); //可以使用Object类的runtimeType属性,获取对象的类型 此时的类型是null

  //命名构造函数
  p = Point.fromJson({'x': 2, 'y': 2});
  print(p);  // 输出 Point(x = 2, y = 2)

  //重定向构造函数
  p = Point.alongXAxis(0);
  print(p); // 输出Point(x = 0, y = 0)

  //调用超类构造函数
  var child = Child.fromJson(1, 2);   //输出 超类命名构造函数
  var child1 = Child(3, 4);  //输出 子类命名构造函数

  //常量构造函数
  var p2 = const Point2(4, 4);
  print(p2);  //输出 Point2(x = 4, y = 4)
  var p21 = Point2(4, 4); //创建的是非 常量对象
  var p22 = const Point2(4, 4);
  print(identical(p2, p21));  //输出 false
  print(identical(p2, p22));  //输出 true

  //工厂方法构造函数
  var singleton1 = Singleton('dongnao');
  var singleton2 = Singleton('damon');
  print(identical(singleton1, singleton2));  //输出 true

  //工厂模式两种方式
  //创建顶级函数
  var footMassage = massageFactory('foot');
  footMassage.doMassage();  //输出 脚底按摩

  //创建工厂构造函数
//  var footMassage = new Massage('foot');
//  footMassage.doMassage();
//  var bodyMassage = new Massage('body');
//  bodyMassage.doMassage();
//  var specialMassage = new Massage('%#@##@##');
//  specialMassage.doMassage();

  //set get
  var rect = new Rectangle(1, 1, 10, 10);
  print(rect.left); //输出 1
  rect.right = 12;
  print(rect.left); //输出 2

  //implement 一个普通类
  var jishi = Jishi();
  jishi.work();  // 输出 jishi work

  //可调用类
  var cf = new ClassFunction();
  var out = cf("dongnao","flutter,","damon");
  print('$out'); // 输出 dongnao flutter, damon!
  print(cf.runtimeType); // 输出 ClassFunction
  print(out.runtimeType); // 输出 String
  print(cf is Function); // 输出 false

  //重载操作符
  final v1 = Vector(2, 3);
  final v2 = Vector(2, 2);
  final r1 = v1 + v2;
  final r2 = v1 - v2;
  print([r1.x, r1.y]);  //输出 [4, 5]
  print([r2.x, r2.y]);  //输出 [0, 1]
}

class Point {
  num x;
  num y;
  var distanceFromOrigin;

  //普通构造函数
//  Point(num x, num y){
//    this.x = x;
//    this.y = y;
//  }

  //简化构造
//  Point(this.x, this.y);

  //命名构造函数
  Point.fromJson(Map json) {
    x = json['x'];
    y = json['y'];
  }

  //重定向构造函数 使用冒号调用其他构造函数
  Point.alongXAxis(num x) : this(x, 0);

  //初始化列表
  Point(this.x, this.y) : distanceFromOrigin = sqrt(x * x + y * y);

  @override
  String toString() {
    // TODO: implement toString
    return 'Point(x = $x, y = $y)';
  }
}

class Parent {
  int x;
  int y;

  //超类命名构造函数不会传递,如果希望使用超类中定义的命名构造函数创建子类,则必须在子类中实现该构造函数
  Parent.fromJson(x, y)
      : x = x,
        y = y {
    print('超类命名构造函数');
  }
}

class Child extends Parent {
  int x;
  int y;

  //如果超类没有默认构造函数, 则你需要手动的调用超类的其他构造函数
  Child(x, y) : super.fromJson(x, y) {
    //调用超类构造函数的参数无法访问 this
    print('子类构造函数');
  }

  //在构造函数的初始化列表中使用 super(),需要把它放到最后
  Child.fromJson(x, y)
      : x = x,
        y = y,
        super.fromJson(x, y) {
    print('子类命名构造函数');
  }
}

class Point2 {
  //定义const构造函数要确保所有实例变量都是final
  final num x;
  final num y;
  static final Point2 origin = const Point2(0, 0);

  //const关键字放在构造函数名称之前,不能有函数体
  const Point2(this.x, this.y);

  @override
  String toString() {
    return 'Point2(x = $x, y = $y)';
  }
}

class Singleton {
  String name;
  static Singleton _cache; //工厂构造函数无法访问 this。所以这里要静态的

  //工厂构造函数,关键字factory
  //工厂构造函数是一种构造函数,与普通构造函数不同,工厂函数不会自动生成实例,而是通过代码来决定返回的实例对象.
//  factory Singleton([String name = 'singleton']) {
////    if(Singleton._cache == null){
////      Singleton._cache=new Singleton._newObject(name);
////    }
////    return Singleton._cache;
//
//    return Singleton._cache ??= Singleton._newObject(name);
//  }
  factory Singleton([String name = 'singleton']) =>
      Singleton._cache ??= Singleton._newObject(name);

//定义一个命名构造函数用来生产实例
  Singleton._newObject(this.name);
}

//工厂函数
class Massage {
  void doMassage(){
    print('按摩');
  }
}
class FootMassage extends Massage {
  @override
  doMassage() {
    print('脚底按摩');
  }
}

class BodyMassage extends Massage {
  @override
  void doMassage() {
    print('全身按摩');
  }
}

class SpecialMassage extends Massage {
  @override
  void doMassage() {
    print('特殊按摩');
  }
}
Massage massageFactory(String type){
  switch (type) {
    case 'foot':
      return new FootMassage();
    case 'body':
      return new BodyMassage();
    default:
      return new SpecialMassage();
  }
}

//工厂模式
//abstract class Massage {
//  factory Massage(String type) {
//    switch (type) {
//      case 'foot':
//        return new FootMassage();
//      case 'body':
//        return new BodyMassage();
//      default:
//        return new SpecialMassage();
//    }
//  }
//
//  void doMassage();
//}
//
//class FootMassage implements Massage {
//  @override
//  doMassage() {
//    print('脚底按摩');
//  }
//}
//
//class BodyMassage implements Massage {
//  @override
//  void doMassage() {
//    print('全身按摩');
//  }
//}
//
//class SpecialMassage implements Massage {
//  @override
//  void doMassage() {
//    print('特殊按摩');
//  }
//}

//setter getter
//每个实例变量都隐含的具有一个 getter, 如果变量不是 final 的则还有一个 setter
//可以通过实行 getter 和 setter 来创建新的属性, 使用 get 和 set 关键字定义 getter 和 setter
class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  // getter 和 setter 的好处是,可以开始使用实例变量,后面可以把实例变量用函数包裹起来,而调用你代码的地方不需要修改。
  //获取right值
  num get right => left + width;
  //设置right值,同时left也发生变化
  set right(num value) => left = value - width;
  //获取bottom值
  num get bottom => top + height;
  //设置bottom值,同时top也发生变化
  set bottom(num value) => top = value - height;
}

//implement 一个普通类
class People {
  void work() {
    print('people work');
  }
}

class Jishi implements People {
  @override
  void work() {
    print('jishi work');
  }
}

//可调用类
class ClassFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

//重载操作符
class Vector {
  final int x;
  final int y;

  const Vector(this.x, this.y);

  //重载+
  Vector operator +(Vector v) {
    return new Vector(x + v.x, y + v.y);
  }

  //重载-
  Vector operator -(Vector v) {
    return new Vector(x - v.x, y - v.y);
  }
}

输出

D:\flutter\bin\cache\dart-sdk\bin\dart.exe --enable-asserts --enable-vm-service:16335 D:\Code\Flutter\FlutterHello\flutter_app\lib\class.dart
lib/class.dart: Warning: Interpreting this as package URI, 'package:flutterapp/class.dart'.
Observatory listening on http://127.0.0.1:16335/qmnwX-zRmj4=/

Point(x = 1, y = 1)
Null
Point(x = 2, y = 2)
Point(x = 0, y = 0)
超类命名构造函数
子类命名构造函数
超类命名构造函数
子类构造函数
Point2(x = 4, y = 4)
false
true
true
脚底按摩
1
2
jishi work
dongnao flutter, damon!
ClassFunction
String
false
[4, 5]
[0, 1]

Process finished with exit code 0

 

### Dart 中命名构造函数使用方法 在 Dart 中,命名构造函数允许在一个类中定义多个构造函数。这种特性非常有用,尤其是在需要不同的方式来创建对象时。以下是关于命名构造函数的具体说明以及示例。 #### 命名构造函数的基本概念 命名构造函数通过 `className.constructorName` 的形式定义[^1]。它与默认构造函数不同之处在于可以拥有自己的名字,并且可以在同一个类中定义多个命名构造函数。这些构造函数既可以调用父类的构造函数[^3],也可以执行额外的操作逻辑。 #### 示例代码 下面是一个完整的例子,展示了如何在 Dart使用命名构造函数: ```dart class Student { String? name; int? age; // 默认构造函数 Student(this.name, this.age); // 命名构造函数 1: 初始化学生信息 Student.init(String name, int age) { this.name = name; this.age = age; print("命名构造函数 init 被调用了"); } // 命名构造函数 2: 复制另一个学生的数据 Student.copy(Student student) : this.name = student.name, this.age = student.age { print("复制了一个学生的信息:name=${this.name}, age=${this.age}"); } } void main() { // 使用默认构造函数 var student1 = Student("Alice", 20); print("Student1: Name=${student1.name}, Age=${student1.age}"); // 使用命名构造函数 init var student2 = Student.init("Bob", 22); print("Student2: Name=${student2.name}, Age=${student2.age}"); // 使用命名构造函数 copy var student3 = Student.copy(student1); print("Student3: Name=${student3.name}, Age=${student3.age}"); } ``` #### 关键点解析 1. **初始化列表** 在命名构造函数中,可以通过冒号 (`:`) 后面的初始化列表直接设置字段值。例如,在 `Student.copy` 构造函数中,`this.name = student.name` 和 `this.age = student.age` 是通过初始化列表完成的。 2. **方法体支持** 命名构造函数不仅可以用来初始化对象,还可以包含方法体以执行其他操作。例如,`Student.init` 和 `Student.copy` 都包含了打印日志的方法体。 3. **与其他构造函数的区别** 命名构造函数不同于工厂构造函数,后者可能返回现有对象或子类实例,而命名构造函数仅能构建当前类的新实例[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值