импорт и использование могут не появляться после объявления типа, если haxe использует магию

Я пытаюсь добавить метод «меньше или равно» (ненавязчиво) к базовым типам, таким как 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) даже если я создам отдельные файлы .hx для каждого класса XXXOrder, будет ли одно и то же имя функции (например, le) вызывать конфликты имен.

3) Есть ли способ обойти ключевое слово using (возможно, с помощью обратного вызова??), чтобы эти классы-расширители можно было хранить в одном файле?

Заранее спасибо.

--- Обновление --- Я попытался переместить операторы 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_.


person tinlyx    schedule 21.12.2013    source источник


Ответы (1)


Вам просто нужно переместить операторы using вверх и сослаться на класс, используя полный путь (package.Module.Class).

Хакс определил, что

Следуя принципам затенения, последние импортированные типы всегда имеют приоритет над предыдущими.

Поэтому, чтобы 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
  }
}
person Andy Li    schedule 22.12.2013
comment
Отлично. Я так и не нашел примера using, где цель определяется на месте. - person tinlyx; 27.12.2013
comment
сгенерированный .le() по-прежнему не работает для исходного примера. Любые идеи? - person tinlyx; 27.12.2013