问题
I am trying to add an less-than-or-equal-to method (non-intrusively) to basic types such as Int, Float or existing/library types that I cannot change. (see my other question how to write a generic compare function in Haxe (haxe3)) I read that the "using" keyword is the way to do it.
What I intend to do is this:
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;
}
}
Now haxe3.01 is giving an error: import and using may not appear after a type declaration
.
I understand that using
is a kind of special import
statement, so probably one can't import inside the same file where the declaration is made.
My questions are:
1) in a use-case like this one, do I have to create a three-line file for each of the XXXOrder
classes? This is rather a pain to maintain.
2) even if I create separate .hx files for each XXXOrder
class, will the same function name (e.g. le
) cause name clashes.
3) Is there a way to work around the using
keyword (maybe using callback??) so that these extender classes can be hold in one file?
Thanks in advance.
--- Update ---
I tried moving using
statements before the class definitions as suggested in the answer. Now compiler is not complaining about the using
statement. But it's complaining about type check failure.
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));
}
}
returns:
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 }
It seems that x.le(y) still does not work inside compare_.
回答1:
You just have to move the using
statements to the top and reference the class using a full path (package.Module.Class).
Haxe defined that
Following the principles of shadowing, the latest types imported always have priority over the previous ones.
So to allow IntOrder not to be always shadowed, put it under FloatOrder.
Here is the demo: 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
}
}
来源:https://stackoverflow.com/questions/20717570/import-and-using-may-not-appear-after-a-type-declaration-the-haxe-using-mag