问题描述
我试图用泛型来实现以下结构。得到一个奇怪的编译器错误,无法找出原因。
class Translator< T:Hashable> {...}
class FooTranslator< String>:Translator< String> {...}
这个想法是Translator使用T作为字典中的一个键的类型。这可以是例如一个字符串或枚举。 Subclass提供了具体的字典。
但是它因此失败:Type'String'不符合协议'Hashable'
但字符串符合Hashable!我疯了吗?它也不适用于Int,它也符合Hashable。如果我用Equatable替换Hashable,它也是行不通的,应该由两者来实现。
如果我删除类型约束,仅用于测试(我也是必须禁用字典,因为我不能使用任何不可散列的键作为键) - 它编译
class Translator< T> ; {...}
class FooTranslator< String>:Translator< String> {...}
我做错了什么?
Translator< String>
就是那个没有约束的类型参数。你根本不需要一个类型参数,我怀疑(即你不希望你的 FooTranslator
是一个泛型类本身。) 正如评论中指出的,在Swift中。您可以声明一个抛弃类型参数,如下所示:
class FooTranslator< T>:Translator< String>
它仍然避免声明一个新的类型参数 String $ c $这是导致问题的原因。这意味着当你不需要任何类型参数时,你会引入一个新的类型参数,但它可能比没有任何其他类型的参数...
这一切都假设你确实需要一个子类,例如添加或覆盖成员。另一方面,如果您只是想要一个类型与 Translator< String>
完全相同,则应该使用类型别名:
typealias FooTranslator = Translator< String>
或者甚至以可怕的方式混合两者,如果您真的想要一个子类但不想要必须以通用的方式引用它:
class GenericFooTranslator< T>:Translator< String>
typealias FooTranslator = GenericFooTranslator< Int>
(请注意,这里的 Int
是故意的而不是字符串
,以显示 Translator
中的 T
isn与 FooTranslator
中的 T
相同。)
I'm trying to implement following structure using generics. Getting a weird compiler error, can't figure out why.
class Translator<T:Hashable> {...}
class FooTranslator<String>:Translator<String> {...}
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.
But it fails because of this: "Type 'String' does not conform to protocol 'Hashable'"
But String conforms to Hashable! Am I nuts? It also doesn't work with Int, which also conforms to Hashable. It also doesn't work if I replace Hashable with Equatable, which should be also implemented by both.
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> {...}
What am I doing wrong?
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.)
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>
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...
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>
(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
.)
这篇关于奇怪的泛型错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!