gpt4 book ai didi

generics - 是否可以对类字段和属性使用 Haxe 类型约束?

转载 作者:行者123 更新时间:2023-12-02 22:05:22 25 4
gpt4 key购买 nike

我有一个带有约束类型参数的方法,我希望能够在具有 x 的任何对象上使用该方法。和y类型 Float :

public static function nearest<T:{var x:Float; var y:Float;}>
(x1:Float, y1:Float, objs:Array<T>, distanceMetric:Float->Float->Float->Float->Float):T {
// Snip. Returns the object nearest to x1,y1
}

这样做的问题是,当 x 时,类型约束检查失败。和/或 y在提供的T是具有 getter 或 setter 的属性,会导致如下错误:

Constraint check failure for nearest.T

Inconsistent access for field x : (get,set) should be (default,default)

我认为将类字段和属性视为与编写通用算法相同的方法会很巧妙。如果这在类型约束下是不可能的,那么有没有办法可以使用 Haxe 3.2 来完成?

最佳答案

扩展@clemos的答案 - 不可能将类字段和属性视为与简单的 typedef 相同,因为 Haxe getter 和 setter 在编译时解析 -有一种替代方法可以处理这个问题。

但是,这有点麻烦。您可以看到它的实际效果 here .

首先,我们在适用于变量和属性的包装器上构建一个抽象:

// let's start with our possible point types
typedef NoGetters = { x:Float, y:Float };
typedef WithProperties = { var x(get,set):Float; var y(get,set):Float; };

// now, let's prepare a common implementation for them
typedef SomePoint2Impl<T> = { obj:T, get_x:Void->Float, get_y:Void->Float };
// and use it in and abstract
abstract SomePoint2<T>(SomePoint2Impl<T>) from SomePoint2Impl<T> {
// these wrap points in the common type
@:from static function fromNoGetters<T:NoGetters>(p:T):SomePoint2<T>
return { obj : p, get_x : function () return p.x, get_y : function () return p.y };
@:from static function fromWithProperties<T:WithProperties>(p:T):SomePoint2<T>
return { obj : p, get_x : function () return p.x, get_y : function () return p.y };

// and this restores the original type from the common one
@:to function toOriginal():T
return this.obj;
}

现在,我们在原始 nearest 方法的简化 Point->Point 版本中使用此抽象并对其进行测试。

// a test class for points with properties
// (points without properties can be tested with anonymous structs)
// don't use @:isVar, so that is clear that the getter was called
class TestPoint {
var _x:Float;
var _y:Float;
public var x(get,set):Float;
function get_x() return _x;
function set_x(x) return _x = x;
public var y(get,set):Float;
function get_y() return _y;
function set_y(y) return _y = y;
public function toString()
return '(x:$x, y:$y)';
public function new(x,y)
{
_x = x;
_y = y;
}
}

class Test {
// a simplified function that takes some "point" and returns it back
// it retains the basic type system problem as `nearest`
public static function test<T>(p:SomePoint2<T>)
return p;

static function main()
{
// some points
var p1 = { x:1., y:2. };
var p2 = new TestPoint(1, 2);

// calls to test
var t1 = test(p1);
var t2 = test(p2);
$type(t1);
$type(t2);

// show that identity has been preserved
// t1,t2 both get cast back to their original types
trace(t1 == p1);
trace(t2 == p2);

// show explicit conversions
trace((t1:{x:Float, y:Float}));
trace((t2:TestPoint));
// trace((t1:TestPoint)); // fails as expected: SomePoint2<{ y : Float, x : Float }> should be TestPoint
}
}

注意:我觉得这个解决方案可以很容易地改进(两个 @:from 实现是相等的),但现在是凌晨 3 点,脑子里什么也没有。如果我最终弄清楚如何简化它,我会回来编辑它。

关于generics - 是否可以对类字段和属性使用 Haxe 类型约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33094772/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com