Date
May. 19th, 2024
 
2024年 4月 12日

Post: Dart Primer 005 : 类

Dart Primer 005 : 类

Published 12:05 May 17, 2018.

Created by @ezra. Categorized in #Programming, and tagged as #Dart.

Source format: Markdown

Table of Content

Dart 是一门使用类单继承的语言, 所有对象都是类的实例, 且所有类都是 Object 类的子类。

定义类

类的定义使用 class 关键字。

class Point {
  num x;
  num y;
  num z;
}

实例化

我们可以通过 new 关键字和构造函数进行类的实例化操作。一个类如果没有显式定义构造函数, 将会有默认的空构造函数。

var point = new Point();
print(point.hasCode);

构造函数

如果只是进行简单的参数传递赋值, 有两种简单的方式:

class Point {
  num x;
  num y;
  num z;

  // 第一个值传递给 this.x,第二个值传递给 this.y
  Point(this.x, this.y, z) {
    this.z = z;
  }
class Point {
  num x;
  num y;
  num z;

  // 命名构造函数, 格式为 Class.name(var param)
  Point.fromeList(var list):
    x = list[0], y = list[1], z = list[2] { // 使用冒号初始化变量
  }

  // 这个构造函数可以简写为
  // Point.fromeList(var list): this(list[0], list[1], list[2]);
}

常量构造函数

如果需要创建不可变的对象, 那么构造函数前需要添加 const 关键字:

class ImmutablePoint {
  final num x;
  final num y;

  // 常量构造函数
  const ImmutablePoint(this.x, this.y);

  // 创建一个常量对象不能用 new,要用 const
  static final ImmutablePoint origin = const ImmutablePoint(0, 0);
}

工厂构造函数

当前面提到的构造函数无法满足需求时, 你还可以选择工厂构造函数, 需要添加 factory 关键字:

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 = new Logger._internal(name);
            _cache[name] = logger;
            return logger;
        }
    }

    Logger._internal(this.name);

    void log(String msg) {
        if (!mute) {
            print(msg);
        }
    }
}

var logger = new Logger('UI');
logger.log('Button clicked');

继承

你可以通过 extends 关键字指明父类, 未指明父类时, 默认继承自 Object 类。

class Rectangle {
  num x;
  num y;
  num width;
  num height;

  Rectangle(num this.height, num this.width);
}

// Square 继承 Rectangle
class Square extends Rectangle {
  // 调用超类的构造函数
  Square(num size): super(size, size);
}

toString()

你可以选择为一个类实现 String toString() 函数:

class Point {
  num x;
  num y;

  Point(this.x, this.y) {}
  String toString() => 'Point(x: $x, y: $y)';
}

void main() {
  var p = new Point(1, 2);
  print(p); // 默认调用 toString() 函数
}

Getter & Setter

每一个字段都对应一对隐式的 Getter/Setter。对于常量, 则只有 Getter 方法。

你可以使用 get/set 进行扩展:

class Rectangle {
  num x;
  num y;
  num width;
  num height;

  Rectangle(this.x, this.y, this.width, this.height);

  // right 和 bottom 两个属性的计算方法:

  num get right => x + width;
  set right(num value) => x = value - width;

  num get bottom => y + height;
  set bottom(num value) => y = value - height;
}

main() {
  var rect = new Rectangle(3, 4, 20, 15);
  assert(rect.x == 3);
  rect.right = 12;
  assert(rect.x == -8);
}

抽象类/接口

通过 abstract 我们可以定义一个抽象类/接口。抽象类不可以无法实例化, 通过 implements 指明并实现。抽象方法不需要关键字声明, 直接使用 ; 结束即可。

// 定义 Shape 抽象类/接口
abstract class Shape {

  // 抽象方法, 是隐式接口的一部分
  num perimeter();
}

// 为 Rectangle 实现 Shape 接口
class Rectangle implements Shape {
  final num height, width;

  Rectangle(num this.height, num this.width);

  // 实现了 Shape 接口要求的 perimeter 方法
  num perimeter() => 2 * height + 2 * width;
}

// Square 继承 Rectangle
class Square extends Rectangle {
  // 调用超类的构造函数
  Square(num size): super(size, size);
}
Pinned Message
HOTODOGO
I'm looking for a SOFTWARE PROJECT DIRECTOR / SOFTWARE R&D DIRECTOR position in a fresh and dynamic company. I would like to gain the right experience and extend my skills while working in great teams and big projects.
Feel free to contact me.
For more information, please view online résumé or download PDF
本人正在寻求任职 软件项目经理 / 软件技术经理 岗位的机会, 希望加⼊某个新鲜⽽充满活⼒的公司。
如有意向请随时 与我联系
更多信息请 查阅在线简历下载 PDF