为什么泛型不编译? [英] Why generics don't compile?
问题描述
我正在尝试使用泛型实现以下结构.遇到编译器错误,无法找出原因.
I'm trying to implement following structure using generics. Getting a compiler error, can't figure out why.
class Translator<T:Hashable> {...}
class FooTranslator<String>:Translator<String> {...}
这个想法是翻译器使用T作为字典中键的类型.例如字符串或枚举.子类提供具体的字典.
The idea is that Translator uses T as the type of a key in a dictionary. This can be e.g. a String or an enum. Subclass provides concrete dictionary.
但是它失败了,因为:类型'String'不符合协议'Hashable'"
But it fails because: "Type 'String' does not conform to protocol 'Hashable'"
但是String符合Hashable.它也不适用于Int,后者也符合Hashable.
But String conforms to Hashable. It also doesn't work with Int, which also conforms to Hashable.
如果我删除类型约束,则仅用于测试(在这里我还必须禁用字典,因为我不能在那里使用任何不可哈希的键作为键)-它会编译
If I remove the type constraint, just for testing (where I also have to disable the dictionary, as I can't use anything not hashable as key there) - it compiles
class Translator<T> {...}
class FooTranslator<String>:Translator<String> {...}
我在做什么错了?
推荐答案
我不是Swift开发人员,但是在Java中看到过类似的问题后,我怀疑问题在于,您现在正在声明一个名为String
因为您要声明class FooTranslator<String>
-所以Translator<String>
中的 argument 类型就是该类型参数,没有任何约束.我怀疑您根本不想要类型参数(即您不希望您的FooTranslator
本身成为泛型类).
I'm not a Swift developer, but having seen similar problems in Java, I suspect the problem is that at the moment you're declaring a type parameter called String
because you're declaring class FooTranslator<String>
- so the type argument in Translator<String>
is just that type parameter, which has no constraints. You don't want a type parameter at all, I suspect (i.e. you don't want your FooTranslator
to be a generic class itself.)
如注释中所述,在Swift的通用子类中类也必须是通用的.您可以声明一个抛弃型参数,像这样:
As noted in comments, in Swift subclasses of a generic class also have to be generic. You could possibly declare a throw-away type parameter, like this:
class FooTranslator<T>:Translator<String>
仍然避免声明一个称为String
的新类型参数,而这正是导致此问题的原因.这意味着当您不想要任何类型参数时就引入了一个新的类型参数,但这可能总比没有好...
which still avoids declaring a new type parameter called String
, which was what was causing the problem. It means you're introducing a new type parameter when you don't want any type parameters, but it's possibly better than nothing...
所有这一切都基于您确实需要一个子类的假设,例如添加或覆盖成员.另一方面,如果只想与Translator<String>
完全相同的类型,则应使用类型别名:
This is all on the assumption that you really need a subclass, e.g. to add or override members. On the other hand, if you just want a type which is exactly the same as Translator<String>
, you should use a type alias instead:
typealias FooTranslator = Translator<String>
或者,如果您确实想要一个子类,但又不想以一种通用的方式引用它,那么甚至以可怕的方式将两者混合:
Or even mix the two in a horrible way, if you genuinely want a subclass but don't want to have to refer to it in a generic way:
class GenericFooTranslator<T>:Translator<String>
typealias FooTranslator = GenericFooTranslator<Int>
(请注意,此处的Int
故意不是String
,以显示Translator
中的T
与FooTranslator
中的T
不同.)
(Note that the Int
here is deliberately not String
, to show that the T
in Translator
isn't the same as the T
in FooTranslator
.)
这篇关于为什么泛型不编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!