“import and using may not appear after a type declaration” — the haxe using magic

♀尐吖头ヾ 提交于 2020-01-06 15:29:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!