我正试图将小于或等于方法(非侵入性)添加到基本类型中,如Int、Float或我无法更改的现有/库类型。(请参阅我的另一个问题,如何在Haxe(haxe3)中编写通用比较函数)我读到"using"关键字是实现这一点的方法
我打算做的是:
class IntOrder {
static public function le(x:Int,y:Int):Bool { return x <= y; }
}
class FloatOrder {
static public function le(x:Float,y:Float):Bool { return x <= y; }
}
class StringOrder {
static public function le(x:String,y:String):Bool {... }
}
//...Other classes
using IntOrder;
using FloatOrder;
using StringOrder;
//... Other using statements
class Main {
@:generic static public function compare_<A:{function le(y:A):Bool;}>(x:A,y:A): Int {
if (x.le(y) && y.le(x)) return 0;
else if (x.le(y)) return -1;
else se return 1;
}
}
现在haxe3.01给出了一个错误:import and using may not appear after a type declaration
。
我知道using
是一种特殊的import
语句,因此可能无法在进行声明的同一文件中导入。我的问题是:
1) 在像这样的用例中,我是否必须为每个XXXOrder
类创建一个三行文件?这是一种很难维持的痛苦。
2) 即使我为每个XXXOrder
类创建单独的.hx文件,相同的函数名(例如le
)是否会导致名称冲突。
3) 有没有办法绕过using
关键字(可能使用callback??),以便将这些扩展程序类保存在一个文件中?
提前谢谢。
---更新---我试着按照答案中的建议,将using
语句移到类定义之前。现在编译器并没有抱怨using
语句。但它在抱怨类型检查失败。
using Main.IntOrder;
using Main.FloatOrder;
using Main.StringOrder;
class IntOrder {
static public function le(x:Int,y:Int):Bool { return x <= y; }
}
class FloatOrder {
static public function le(x:Float,y:Float):Bool { return x <= y; }
}
class StringOrder {
static public function le(x:String,y:String):Bool { return true; }
}
class Main {
@:generic static public function compare_<A:{function le(y:A):Bool;}>(x:A,y:A): Int {
if (x.le(y) && y.le(x)) return 0;
else if (x.le(y)) return -1;
else return 1;
}
static public function main() {
Sys.print(compare_(1,2));
}
}
退货:
Main.hx:22: characters 12-25 : Constraint check failure for compare_.A
Main.hx:22: characters 12-25 : Int should be { le : y : Int -> Bool }
似乎x.le(y)在compare_内仍然不起作用。
您只需要将using
语句移到顶部,并使用完整路径(package.Module.class)引用该类。
Haxe定义
遵循阴影的原则,导入的最新类型总是比以前的优先。
因此,为了使IntOrder不总是被遮蔽,请将其放在FloatOrder下。
以下是演示:http://try.haxe.org/#8E07D
using Test.FloatOrder;
using Test.IntOrder;
class IntOrder {
static public function le(x:Int,y:Int) return "IntOrder";
}
class FloatOrder {
static public function le(x:Float,y:Float) return "FloatOrder";
}
class Test {
static function main():Void {
trace(1.le(1)); //IntOrder
trace(1.1.le(1)); //FloatOrder
}
}