【问题标题】:Explain @:remove @:generic metadata combination解释@:remove @:generic 元数据组合
【发布时间】:2019-12-09 13:37:26
【问题描述】:

考虑带有类型参数的类,它应该用作Map 键。

class Foo<K> {
  var map: Map<K, Dynamic> = new Map();
}

编译时出现错误Type parameters of multi type abstracts must be known

原因是可以理解的——Mapabstract,它的底层类型是根据键类型来选择的,所以在编译new Map()表达式时应该知道键类型。另一方面,具有类型参数的非泛型类型为所有参数编译一次。

看起来添加@:generic 元数据应该会有所帮助。但实际上并没有。我的猜测是这是因为 haxe 编译器编译 @:generic 类型与编译非泛型类型相同,然后才为泛型类型做一些额外的工作。所以我在想,在 haxe 中拥有一个由 type 参数定义的键类型的 Map 是不可能的。

但最近我偶然发现了这个问题:https://github.com/HaxeFoundation/haxe/issues/2537 Simn 的回答说,这可以通过添加@:remove @:generic 元数据来完成。它确实有效。

@:remove @:generic
class Foo<K> {
  var map: Map<K, Dynamic> = new Map();
}

对我来说,这看起来很神奇,我对此感到不舒服。在文档中我只看到 @:remove 导致在生成之前从所有实现类中删除接口。这并不能解释为什么会这样。

【问题讨论】:

    标签: haxe


    【解决方案1】:

    如果您将 Map 替换为 haxe.ds.BalancedTree 并仅使用 @:generic 而不使用 @:remove,您将看到在您的目标上生成的类 Foo 包含 new BalancedTree(对象是动态的)。这意味着, Foo 类持有通用 BalancedTree 类型,而 Foo_String 例如持有通用 BalancedTree 类型。现在,如果您返回您的地图,您将看到“Abstract haxe.ds.Map 没有接受 haxe.IMap 的 @:to 函数”,例如不存在 Map 实现。这就是为什么您需要使用 @:remove ,它实际上将停止生成 Foo 类,或者至少从 Foo 中删除 new Map (@:remove “导致接口被删除”在这里具有误导性)

    【讨论】:

    • 编译器只为实际使用的类型参数生成泛型实现。 @:remove 在这里添加了什么?为什么@:generic 还不够?
    • 你应该问问 Haxe 团队为什么会这样。例如,非泛型 Foo 可以用作 var f:Foo = new Foo(),但泛型将失败,无法将 Foo 转换为 Foo。可能是因为它是关于通用与非通用的性能(速度)。但是你应该问(打开一个问题),因为你“发现”了这一点,我在这里只是解释引擎盖下发生了什么。
    猜你喜欢
    • 2023-04-02
    • 2021-10-31
    • 1970-01-01
    • 2010-12-29
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多