目录
类
构造函数
命名构造函数
重定向构造函数
常量构造函数
工厂构造函数
Getters 和 Setters
初始化列表
可覆写的操作符
类

创建一个dart文件,名称全小写,里面的类可以按照驼峰命名法。文件名和类名可以不保持统一,这个跟Java有明显区别。

        Dart是一种面向对象的语言,具有类和基于mixin的继承。每个对象都是一个类的实例,所有的类都是Object的子类。基于mixin的继承意味着,尽管每个类(除了Object)都只有一个超类,但类主体可以在多个类层次结构中重用。
示例中向你展示了一个包含2个属性、2个构造函数以及1个函数的类。
//每个实例变量都会自动生成一个 getter 方法(隐含的)。 非final 实例变量还会自动生成一个 setter 方法。
class SccPoint{
  late num x;
  num y;
  //构造函数
  SccPoint(this.x,this.y);
  //命名构造函数
  //Dart 不支持构造函数的重载
  SccPoint.y(this.y){
    x = 0;
  }
  //函数
  void position(){
    print("x=$x,y=$y");
  }
}
构造函数
由于把构造函数参数赋值给实例变量的场景太常见了, Dart 提供了一个语法糖来简化这个操作:
  //构造函数
  SccPoint(this.x,this.y);
命名构造函数
        Dart 不支持构造函数的重载,而采用了命名构造函数为一个类实现多个构造函数:
  //命名构造函数
  //Dart 不支持构造函数的重载
  SccPoint.y(this.y){
    x = 0;
  }
「运行结果」

重定向构造函数
        有时候一个构造函数会调动类中的其他构造函数(在Java中就是 this(...))。 一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号调用其他构造函数。
class SccPoint{
  num x;
  num y;
  //构造函数
  SccPoint(this.x,this.y);
  //命名构造函数
  SccPoint.y(num y):this(0,y);//调用上面的构造函数
}
常量构造函数
        如果你的类提供一个状态不变的对象,你可以把这些对象 定义为编译时常量。要实现这个功能,需要定义一个 const 构造函数, 并且声明所有类的变量为 final。
class ImmutablePoint {
  final num x;
  final num y;
  //常量构造函数
  const ImmutablePoint(this.x, this.y);
}
void main(){
  //构造两个相同的编译时常量会生成一个单一的、规范的实例
  var p3 = const ImmutablePoint(1,2);
  var p4 = const ImmutablePoint(1,2);
  print(p3 == p4); // true
  print(identical(p3, p4));// true
}
工厂构造函数
        当实现一个使用 factory 关键词修饰的构造函数时,这个构造函数不必创建类的新实例。例如,一个工厂构造函数 可能从缓存中获取一个实例并返回,或者 返回一个子类型的实例。(工厂构造函数无法访问 this)
class Logger {
  final String name;
  bool mute = false;
  // _cache 变量是库私有的,因为在其名字前面有下划线。
  static final Map<String, Logger> _cache =
  <String, Logger>{};
  factory Logger(String name) {
    return _cache.putIfAbsent(
        name, () => Logger._internal(name)); //工厂构造函数里可以调用其他构造函数。
  }
  factory Logger.fromJson(Map<String, Object> json) {
    return Logger(json['name'].toString());
  }
  //以 _ 开头的函数是库私有的,无法在库外使用
  Logger._internal(this.name);
  void log(String msg) {
    if (!mute) print(msg);
  }
}
借助工厂构造函数能够实现单例:
//使用工厂构造实现单例
class Manager {
  static final Manager _singleton = Manager._internal();
  factory Manager() {
    return _singleton;
  }
  Manager._internal();
}
//使用
  var m1 = Manager();
  var m2 = Manager();
  print(m1 == m2); // true
Getters 和 Setters
        Dart中每个实例变量都隐含的具有一个 getter, 如果变量不是 final 的则还有一个 setter。可以通过实现 getter 和 setter 来创建新的属性, 使用 get 和 set 关键字定义 getter 和 setter:
class SccPoint{
  num x;
  num y;
  SccPoint(this.x,this.y);
  void position(){
    print("x=$x,y=$y,a=$a");
  }
  //使用 get定义了一个 a 属性(不可与原属性同名)
  num get a   => x+y;
  set a(num b) => x=x+b;
}
void main() {
  var p9 = SccPoint(3, 9);
  p9.position();//x=3,y=9,a=12
  p9.a=10;
  p9.position();//x=13,y=9,a=22
}
注意:在get与set中使用自身会导致Stack Overflow(递归)
调用自身:

初始化列表
在构造函数函数体执行之前会首先执行初始化列表,非常适合用来设置 final 变量的值。
class SccPoint{
  num? x;
  num? y;
  SccPoint.fromJson(Map<String, num> json)
      : x = json['x'],
        y = json['y'] {
    print('In SccPoint.fromJson(): ($x, $y)');
  }
}
  //使用
  SccPoint.fromJson({"x":15,"y":20});
可覆写的操作符
把已经定义的、有一定功能的操作符进行重新定义。可以重新定义的操作符有:
| < | + | | | [] | 
|---|---|---|---|
| > | / | ^ | []= | 
| <= | ~/ | & | ~ | 
| >= | * | << | == | 
| – | % | >> | 
        比如:dart.math包下Point类就重写了 +、-、*、==这几个操作符。
  Point<T> operator +(Point<T> other) {
    return Point<T>((x + other.x) as T, (y + other.y) as T);
  }
  Point<T> operator *(num /*T|int*/ factor) {
    return Point<T>((x * factor) as T, (y * factor) as T);
  }
操作符重载函数的名字是“关键字 operator +以及紧跟其后的一个 Dart 预定义的操作符。
class SccPoint{
  num x;
  num y;
  SccPoint(this.x,this.y);
  //加
  SccPoint operator +(SccPoint point){
    return SccPoint(x+point.x,y+point.y);
  }
  //乘
  SccPoint operator *(SccPoint point){
    return SccPoint(x*point.x,y*point.y);
  }
  void position(){
    print("x=$x,y=$y");
  }
}
使用
//导入类文件(最好全路径),看起来直观一些
import 'package:flutter_demo_scc/scc_point.dart';
//导入类文件(相对路径),两种都可以
// import 'scc_point.dart';
void main() {
  var p5 = SccPoint(3, 5);
  var p6 = SccPoint(2, 7);
  var p7 = p5+p6;
  var p8 = p5*p6;
  p5.position();//x=3,y=5
  p6.position();//x=2,y=7
  p7.position();//x=5,y=12
  p8.position();//x=6,y=35
}



















