我希望以下代码在两种情况下都能打印“扩展名”。但扩展的类型约束不会对包含的泛型类型生效。在约束协议时我也看到相同的行为。
class Generic1<T1> {
func doSomething() {
print("base")
}
}
extension Generic1 where T1 == String {
func doSomething() {
print("extension")
}
}
class Generic2<T2> {
private let generic1 = Generic1<T2>()
func doSomething() {
generic1.doSomething()
}
}
Generic1<String>().doSomething() // prints extension
Generic2<String>().doSomething() // prints base
我目前唯一的解决方法是限制外部泛型,如下所示:
extension Generic2 where T2 == String {
func doSomething() {
generic1.doSomething()
}
}
为什么会这样?有更好的解决方案吗?
修改:为了完整起见,适合我案例的解决方法如下:
class Generic1<T1> {
func doSomething() {
print("base")
}
}
class StringGeneric1: Generic1<String> {
override func doSomething() {
print("extension")
}
}
class Generic2<T2> {
private let generic1: Generic1<T2>
init (_ generic1: Generic1<T2>) {
self.generic1 = generic1
}
func doSomething() {
generic1.doSomething()
}
}
Generic1<String>().doSomething() // prints "base"
Generic2<String>(StringGeneric1()).doSomething() // prints "extension"
答案 0 :(得分:1)
问题是扩展中定义的方法是静态分派的。所以当你有:
class Generic2<T2> {
private let generic1 = Generic1<T2>()
func doSomething() {
generic1.doSomething()
}
}
编译器无法在此知道T2
是否将成为String
,因此它会生成对基类中方法的调用。当您明确指定T2
为String
时,使用该信息,编译器可以在此处生成对扩展方法的调用。但是,否则,T2
的类型在运行时才会知道,因此您无法通过静态分派来访问扩展方法。
答案 1 :(得分:0)
使用Swift 4.2添加conditional conformances时可以解决这个问题