Method(方法)

方法是为对象提供行为的函数,分为 4 大类:实例方法、运算符重载、Getter/Setter、抽象方法。

1. Instance methods 实例方法

  1. 属于类实例对象的方法;
  2. 可直接访问实例变量,可使用 this 关键字;
  3. 有完整函数体,能完成业务计算、逻辑操作。
import 'dart:math';

class Point {
  final double x;
  final double y;

  // 构造函数初始化实例变量
  Point(this.x, this.y);

  // 实例方法:计算两点之间距离
  double distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}

void main() {
  Point p1 = Point(0, 0);
  Point p2 = Point(3, 4);
  print(p1.distanceTo(p2)); // 输出 5.0
}Code language: JavaScript (javascript)

2. Operators 运算符重载

  1. 大部分运算符本质是带特殊命名的实例方法;
  2. 声明格式:operator 运算符(参数) 返回类型 { ... }
  3. 支持重载运算符清单:
    < > <= >= == ~
    - + / ~/ * %
    | ˆ & << >>> >>
    []= []
  4. 内置运算符不可重载(如 !=,底层由 Dart 自动实现,无需手动定义);
  5. 重载 == 必须同步重写 hashCode,否则判等会出现异常。
class Vector {
  final int x, y;

  Vector(this.x, this.y);

  // 重载 + 向量加法
  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  // 重载 - 向量减法
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);

  // 重载 == 相等判断
  @override
  bool operator ==(Object other) =>
      other is Vector && x == other.x && y == other.y;

  // 配套重写 hashCode
  @override
  int get hashCode => Object.hash(x, y);
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
  print(v + w);
}Code language: JavaScript (javascript)

通过重载函数后,我们可以像数字一样对两个Vector的对象进行+、-、==等这些平常用在数字上面的操作。

3. Getters and setters 存取器

  1. get:只读方法,读取计算属性,无参数;
  2. set:写入方法,修改关联变量,仅有一个参数;
  3. 所有实例变量自带隐式 getter,可变变量自带隐式 setter;
  4. 优势:后期可把普通变量改成计算逻辑,外部调用代码无需修改;
  5. 自增/自减 ++/-- 会仅调用一次 getter,缓存值避免副作用。
/// 屏幕坐标系矩形,原点(0,0)在左上角
class Rectangle {
  double left, top, width, height;

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

  // Getter:计算右边界
  double get right => left + width;

  // Setter:赋值右边界,反向更新 left
  set right(double value) => left = value - width;

  // Getter:计算下边界
  double get bottom => top + height;

  // Setter:赋值下边界,反向更新 top
  set bottom(double value) => top = value - height;
}

void main() {
  var rect = Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);

  // 调用 setter
  rect.right = 12;
  assert(rect.left == -8);
  print(rect.left); // -8
}Code language: JavaScript (javascript)

4. Abstract methods 抽象方法

  1. 仅定义接口,无方法体,用分号 ; 代替函数实现;
  2. 只能存在于 abstract class 抽象类 / mixin 混入类中;
  3. 子类必须重写并实现全部抽象方法,否则子类也要标记为 abstract
// 抽象类,包含抽象方法
abstract class Doer {
  // 抽象方法:只有声明,无实现
  void doSomething();
}

// 普通子类,必须实现父类所有抽象方法
class EffectiveDoer extends Doer {
  @override
  void doSomething() {
    print("执行具体业务逻辑");
  }
}

void main() {
  Doer worker = EffectiveDoer();
  worker.doSomething(); // 输出:执行具体业务逻辑
}Code language: JavaScript (javascript)

对比

方法类型核心特征语法标识使用场景
实例方法 Instance访问实例变量、完整逻辑体普通函数定义对象常规行为(计算、业务操作)
运算符重载 Operator特殊命名实例方法,关键字 operatoroperator +()自定义对象加减、下标、相等判断
Getter/Setter读写属性,get无参、set单参数get / set封装计算属性,对外统一读写入口
抽象方法 Abstract无方法体,仅声明接口方法后直接 ;抽象父类定义规范,强制子类实现

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注