如何在Haxe泛型类的类型之间使用运算符



我想在泛型类类型的实例之间使用常见的比较运算符(如<>==(,如(try.haxe.org(:

class Comp<T> {
var _val: T;
public function new(val: T) _val = val;
// leads to error: Cannot compare Comp.T and Comp.T
public function gt(val: T):Bool return _val > val;
}
class Test {
static function main() {
var intComp = new Comp<Int>(5);
trace(intComp.gt(3));
trace(intComp.gt(6));

var strComp = new Comp<String>("baz");
trace(strComp.gt("bar"));
trace(strComp.gt("foo"));
}
}

用这段代码,我得到了编译时错误——";无法比较Comp.T和Comp.T";。这是有意义的,因为你永远不知道T类型是什么,它会被常见的运算符所比较吗。但我的具体调用new Comp<Int>new Comp<String>清楚地表明了这种操作是可能的。

如何限制T类只有";操作员的可比";类型,如class Comp<T:HaveComparisonOperators>?或者,我可能应该对编译器说,在泛型类被强制使用具体类型之前,不要分析它的代码?当然,我可以为Int和String类型制作两种变体,但除了方法中的类型声明外,代码将几乎相同。

理想情况下,Haxe可以改进为使用Int|String之类的约束,不幸的是,只有Int&支持字符串,这是没有意义的。

然而,您可以使用抽象类型来完成任务,不知道它是否可以优化。

abstract Comparable(Dynamic) from Int from String to Int to String {
@:op(A > B)
public static function gt(lhs, rhs:Dynamic):Bool {
return (lhs:Dynamic) > rhs;
}
}
class Comp<T:Comparable> {
var _val: Comparable;
public function new(val: T) _val = val;
public function gt(val:T):Bool return _val > val;
}
class Test {
static function main() {
var intComp = new Comp<Int>(5);
trace(intComp.gt(3));
trace(intComp.gt(6));

var strComp = new Comp<String>("baz");
trace(strComp.gt("bar"));
trace(strComp.gt("foo"));
}
}

我已经设法覆盖了类型检查,并认为这是一个非常糟糕的解决方案,但它正在工作:

class Comp<T> {
var _val: T;
public function new(val: T) _val = val;
public function gt(val:T):Bool return (_val:Dynamic) > (val:Dynamic);
}
abstract Entity(Int) from Int to Int {
public function new(val) this = val;
}
typedef IntArray = Array<Int>;
class AnyClass {
public function new(a) {}
}
class Test {
static function main() {
var intComp = new Comp<Int>(5);
trace(intComp.gt(3));
trace(intComp.gt(6));

var strComp = new Comp<String>("baz");
trace(strComp.gt("bar"));
trace(strComp.gt("foo"));

var entComp = new Comp<Entity>(new Entity(55));
trace(entComp.gt(new Entity(33)));
trace(entComp.gt(new Entity(66)));

var shouldFail1 = new Comp<IntArray>([5, 5]); // JS will just compare arrays, voila
trace(shouldFail1.gt([5, 3]));
trace(shouldFail1.gt([5, 6]));

var shouldFail2 = new Comp<AnyClass>(new AnyClass(5)); // WTF???
trace(shouldFail2.gt(new AnyClass(3)));
trace(shouldFail2.gt(new AnyClass(6)));
}
}

让事情变得简单,不要做得太过火。

typedef IntArray = Array<Int>;
abstract Comparable(Dynamic) from ID from Int from String to ID to Int to String {
@:op(A > B)
public static inline function gt(lhs, rhs:Dynamic):Bool {
return (lhs:Dynamic) > rhs;
}
}
class Comp<T:Comparable> {
var _val: Comparable;
public function new(val: T) _val = val;
public function gt(val:T):Bool return _val > val;
}
abstract ID(Int) from Int to Int {
public inline function new(v:Int) this = v;
}
class AnyClass {
public function new(a) {}
}
class Test {
static function main() {
var intComp:Comparable = new ID(1);
trace(intComp > 3);
trace(intComp > 6);

var strComp:Comparable = "baz";
trace(strComp > "bar");
trace(strComp > "foo");
var shouldFail1 = new Comp<IntArray>([5, 5]); // Constraint check failure ... IntArray should be Comparable
var shouldFail2 = new Comp<AnyClass>(new AnyClass(5)); // Constraint check failure ... AnyClass should be Comparable
}
}

最新更新