ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
抽象类型通过添加 `@:op` 元数据到类字段,允许一元和二元运算符的重载: ~~~ abstract MyAbstract(String) { public inline function new(s:String) { this = s; } @:op(A * B) public function repeat(rhs:Int):MyAbstract { var s:StringBuf = new StringBuf(); for (i in 0...rhs) s.add(this); return new MyAbstract(s.toString()); } } class Main { static public function main() { var a = new MyAbstract("foo"); trace(a * 3); // foofoofoo } } ~~~ 通过默认的 `@:op(A*B)`,当左面的值类型是 `MyAbstract` 而且右侧值是 Int 类型的时候,函数 `repeat` 作为乘法 `*` 运算符的运算符。用法在第17行显示,编译到 JavaScript 之后代码成为这样: ~~~ console.log(_AbstractOperatorOverload.MyAbstract_Impl_.repeat(a,3)); ~~~ 类似于通过 [类字段(第2.8.1)](http://#) 方式隐式转换,重载之后的方法的调用被插入到需要的地方。 示例中的 `repeat` 函数是不可交换的:当 `MyAbstract * Int` 工作,`Int * MyAbstract` 则不工作。如果这应该同时允许,可以添加` @:commutative` 元数据。如果它只可以为 `Int * MyAbstract` 工作,而不是为 `MyAbstract * Int`,重载方法可以被设置为 `static`,接受 Int 和 MyAbstract 分别作为第一个和第二个类型。 重载一元运算符是相似的: ~~~ abstract MyAbstract(String) { public inline function new(s:String) { this = s; } @:op(++A) public function pre() return "pre" + this; @:op(A++) public function post() return this + "post"; } class Main { static public function main() { var a = new MyAbstract("foo"); trace(++a); // prefoo trace(a++); // foopost } } ~~~ 二元运算和一元运算符重载都可以返回任何类型。 **暴露潜在类型的操作** 还可以省略 `@:op` 函数的方法体,但是只有抽象类型的潜在类型允许涉及的操作,并且结果类型可以被赋值回抽象类型的时候。 ~~~ abstract MyAbstractInt(Int) from Int to Int { // 下面一行从潜在类型Int暴露 (A>B)操作符 // 注意,并没有使用函数体 @:op(A > B) static function gt( a:MyAbstractInt, b:MyAbstractInt ) : Bool; } class Main { static function main() { var a:MyAbstractInt = 42; if(a > 0) trace(’Works fine, > operation implemented!’); // 小于操作符没有实现 // 这会引起一个 “不能对比MyAbstractInt 和 Int”的错误: if(a < 100) { } } } ~~~