Generics 为什么泛型不';不编译?
我试图使用泛型实现以下结构。获取编译器错误,无法找出原因Generics 为什么泛型不';不编译?,generics,swift,Generics,Swift,我试图使用泛型实现以下结构。获取编译器错误,无法找出原因 class Translator<T:Hashable> {...} class FooTranslator<String>:Translator<String> {...} 类转换器{…} 类FootTranslator:转换器{…} 其思想是翻译器使用T作为字典中的键类型。例如,可以是字符串或枚举。子类提供了具体的字典 但它失败了,因为:“类型‘String’不符合协议‘Hashable’”
class Translator<T:Hashable> {...}
class FooTranslator<String>:Translator<String> {...}
类转换器{…}
类FootTranslator:转换器{…}
其思想是翻译器使用T作为字典中的键类型。例如,可以是字符串或枚举。子类提供了具体的字典
但它失败了,因为:“类型‘String’不符合协议‘Hashable’”
但是字符串符合Hashable。它也不适用于Int,Int也符合Hashable
如果我删除类型约束,只是为了测试(我还必须禁用字典,因为我不能使用任何不可散列的键),它会编译
class Translator<T> {...}
class FooTranslator<String>:Translator<String> {...}
类转换器{…}
类FootTranslator:转换器{…}
我做错了什么?我不是一个敏捷的开发人员,但在Java中也遇到过类似的问题,我怀疑问题在于,现在您正在声明一个名为
String
的类型参数,因为您正在声明类FootTranslator
-所以Translator
中的类型参数就是那个类型参数,没有任何限制。我猜想,您根本不需要类型参数(也就是说,您不希望您的FooTranslator
本身是泛型类)
如评论中所述,在Swift中。您可能会声明一个一次性类型参数,如下所示:
class FooTranslator<T>:Translator<String>
或者甚至以一种可怕的方式将二者混合,如果您真的想要一个子类,但不想以通用的方式引用它:
class GenericFooTranslator<T>:Translator<String>
typealias FooTranslator = GenericFooTranslator<Int>
class GenericFootTranslator:转换器
typealias FootTranslator=通用FootTranslator
(注意这里的
Int
不是String
,为了表明Translator
中的T
与FooTranslator
中的T
不同)首先,让我们解释一下错误:
class Foo<T: Hashable>
class SubFoo<T: Hashable> : Foo<T> { }
鉴于:
class Foo<T:Hashable> { }
class SubFoo<String> : Foo<String> { }
由于使用了未声明的类型,此行为T
生成一个错误
然后,如果我们将行更改为:
class SubFoo<T> : Foo<T> { }
这是完全有效的Swift,它编译得很好
相反,如果我们想要的是对泛型类进行子类化,并向泛型类添加方法或属性,那么我们需要的是一个类或协议,它将使我们的泛型更具体地满足我们的需要 回到最初的问题,让我们首先消除错误:
class Foo<T: Hashable>
class SubFoo<T: Hashable> : Foo<T> { }
这是完全正确的
另外,请注意,我们实际上不必从哈希表继承:
protocol MyProtocol { }
class Foo<T: Hashable> { }
class SubFoo<T: Hashable, MyProtocol> { }
协议MyProtocol{}
类Foo{}
类子对象{}
这也是完全正确的
但是,请注意,无论出于何种原因,Swift都不允许您在这里使用类。例如:
class MyClass : Hashable { }
class Foo<T: Hashable> { }
class SubFoo<T: MyClass> : Foo<T> { }
classmyclass:Hashable{}
类Foo{}
类subfo:Foo{}
斯威夫特神秘地抱怨“T”不符合“Hashable”(即使我们添加了必要的代码使其符合要求)
最后,正确的方法,也是最快捷的合适方法是编写一个新的协议,该协议继承自“Hashable”,并添加您需要的任何功能
我们的子类接受一个字符串并不十分重要。重要的是,无论我们的子类接受什么,它都具有我们所做的任何事情所需的必要方法和属性。不是这样。关于这一点,有一个快速的问题/限制,请参见@lxx:Ick。我怀疑这仍然是原因,但y您需要一个不同的解决方案。我已经用一个可能的解决方案编辑了我的答案,以供尝试。@Ixx:对-我不清楚您是否因为其他原因需要一个子类,其中类型别名不合适。我将进一步编辑答案。
class SubFoo<T: String> : Foo<T> { }
protocol MyProtocol : Hashable { }
class Foo<T: Hashable> { }
class SubFoo<T: MyProtocol> : Foo<T> { }
protocol MyProtocol { }
class Foo<T: Hashable> { }
class SubFoo<T: Hashable, MyProtocol> { }
class MyClass : Hashable { }
class Foo<T: Hashable> { }
class SubFoo<T: MyClass> : Foo<T> { }