Dart 中内置类型的重载运算符
Overload Operator for Built-in Type in Dart
考虑以下 Dart 代码:
class Vec2 {
num x, y;
Vec2(this.x, this.y);
Vec2 operator*(num rhs) => Vec2(x * rhs, y * rhs);
String toString() => "<$x, $y>";
}
void main() => print(Vec2(1, 2) * 3);
输出符合预期:
<3, 6>
但是,这仅在表达式左侧为 Vec2
且右侧为 num
时有效。在这种情况下,我希望乘法运算符是可交换的,所以我写了以下扩展:
extension Vec2Util on num {
Vec2 operator*(Vec2 rhs) => Vec2(rhs.x * this, rhs.y * this);
}
人们自然会期望以下代码产生与第一个片段相同的输出:
void main() {
num x = 3;
print("${x * Vec2(1, 2)}");
}
但是,编译器反而报告 The argument type 'Vec2' can't be assigned to the parameter type 'num'.
在这种情况下,编译器似乎正在将乘法解析为 num operator*(num rhs)
,然后抱怨我的 Vec2
不能作为 num
操作数传入。为什么编译器显然无视我的扩展?创建这样的自定义交换运算符的正确方法是什么?
你不能为所欲为。
Dart user-definable 二元运算符都是第一个操作数上的方法。做 e1 + e2
是 kind-of 就像 做 e1.+(e2)
其中 +
是方法的名称,除了你不能正常调用方法 +
.
为了能够做到 3 * vector
,您需要在 3
.
上使用该方法
您不能将方法添加到其他人的 class 中,除非不修改他们的源代码,而且 int
是一个系统 class,所以即使那样也是不可能的。
您不能使用扩展方法,因为当接收器类型已经具有同名的实例方法时,扩展方法不适用。
并且 int
定义了 所有 运算符。
(这就像 user-definable 运算符正是从 int
的需要中选择的,这绝对不是巧合。这在 Dart 中并不新鲜,运算符回到 C 和 Java。)
所以,你可以在 int
上定义一个扩展方法,但无论如何你都不能调用它,不是没有覆盖:
extension MyInt on int {
Vector operator *(Vector other) => other.scalerMultiplication(this);
}
... MyInt(3) * vector ...
这比交换操作数 更复杂。
考虑以下 Dart 代码:
class Vec2 {
num x, y;
Vec2(this.x, this.y);
Vec2 operator*(num rhs) => Vec2(x * rhs, y * rhs);
String toString() => "<$x, $y>";
}
void main() => print(Vec2(1, 2) * 3);
输出符合预期:
<3, 6>
但是,这仅在表达式左侧为 Vec2
且右侧为 num
时有效。在这种情况下,我希望乘法运算符是可交换的,所以我写了以下扩展:
extension Vec2Util on num {
Vec2 operator*(Vec2 rhs) => Vec2(rhs.x * this, rhs.y * this);
}
人们自然会期望以下代码产生与第一个片段相同的输出:
void main() {
num x = 3;
print("${x * Vec2(1, 2)}");
}
但是,编译器反而报告 The argument type 'Vec2' can't be assigned to the parameter type 'num'.
在这种情况下,编译器似乎正在将乘法解析为 num operator*(num rhs)
,然后抱怨我的 Vec2
不能作为 num
操作数传入。为什么编译器显然无视我的扩展?创建这样的自定义交换运算符的正确方法是什么?
你不能为所欲为。
Dart user-definable 二元运算符都是第一个操作数上的方法。做 e1 + e2
是 kind-of 就像 做 e1.+(e2)
其中 +
是方法的名称,除了你不能正常调用方法 +
.
为了能够做到 3 * vector
,您需要在 3
.
您不能将方法添加到其他人的 class 中,除非不修改他们的源代码,而且 int
是一个系统 class,所以即使那样也是不可能的。
您不能使用扩展方法,因为当接收器类型已经具有同名的实例方法时,扩展方法不适用。
并且 int
定义了 所有 运算符。
(这就像 user-definable 运算符正是从 int
的需要中选择的,这绝对不是巧合。这在 Dart 中并不新鲜,运算符回到 C 和 Java。)
所以,你可以在 int
上定义一个扩展方法,但无论如何你都不能调用它,不是没有覆盖:
extension MyInt on int {
Vector operator *(Vector other) => other.scalerMultiplication(this);
}
... MyInt(3) * vector ...
这比交换操作数 更复杂。