如何解决如何在 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&String,这是没有意义的。
但是,您可以使用抽象类型来完成工作,不知道是否可以优化。
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"));
}
}
,
我已经设法override type checking并认为这是一个非常糟糕的解决方案,但它有效:
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
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。