为什么这个通用的基于协议的框架不能编译?
Why won't this generic protocol-based framework compile?
下面是我在 Xcode 9 Beta 5 中开发的 Swift 4 框架的 SSCCE:
// MARK: - Protocols
public protocol BaseFoo {
associatedtype FooBar: Bar
}
public protocol Bar {
associatedtype BarData: DataHolder
}
public extension Bar {
public typealias Callback = BarCallback<BarData>
}
public typealias BarCallback<Result: DataHolder> = (Result?, Error?) -> Void
public protocol DataHolder {
}
// MARK: - Implementations
public class MyFoo: BaseFoo { // Does not compile
public typealias FooBar = MyBar
}
public protocol MyBar: Bar where BarData: MyDataHolder {
}
public protocol MyDataHolder: DataHolder {
}
但是编译器抱怨“Type 'MyFoo' does not conform to protocol 'BaseFoo'
”。 Xcode 询问 "Do you want to add protocol stubs?",当我单击 "Fix" 时,它会这样做:
public class MyFoo: BaseFoo {
public typealias FooBar = <#type#>
public typealias FooBar = MyBar
}
这似乎表明 MyBar
不是满足 FooBar
的正确类型,但它显然是一个 DataHolder
,正如所要求的那样。 这是怎么回事,我该如何解决?
当我尝试使用 Swift 3 进行编译时,我对此有了一些了解,这只需要很少的更改。现在,我收到两个错误:
public class MyFoo: BaseFoo { // Type 'MyFoo' does not conform to protocol 'BaseFoo'
public typealias FooBar = MyBar // Protocol 'MyBar' can only be used as a generic constraint because it has Self or associated type requirements
}
啊哈!现在这是我习惯处理的错误。所以,我把它作为通用参数放在 class 声明中:
public class MyFoo<_MyBar: MyBar>: BaseFoo {
public typealias FooBar = _MyBar
}
现在它编译得很好!将该修复程序带回 Swift 4 会得到相同的结果;现在它编译得很好。
所以问题是MyBar
过于泛化,不能直接作为类型使用,需要通过泛型参数进行抽象。
下面是我在 Xcode 9 Beta 5 中开发的 Swift 4 框架的 SSCCE:
// MARK: - Protocols
public protocol BaseFoo {
associatedtype FooBar: Bar
}
public protocol Bar {
associatedtype BarData: DataHolder
}
public extension Bar {
public typealias Callback = BarCallback<BarData>
}
public typealias BarCallback<Result: DataHolder> = (Result?, Error?) -> Void
public protocol DataHolder {
}
// MARK: - Implementations
public class MyFoo: BaseFoo { // Does not compile
public typealias FooBar = MyBar
}
public protocol MyBar: Bar where BarData: MyDataHolder {
}
public protocol MyDataHolder: DataHolder {
}
但是编译器抱怨“Type 'MyFoo' does not conform to protocol 'BaseFoo'
”。 Xcode 询问 "Do you want to add protocol stubs?",当我单击 "Fix" 时,它会这样做:
public class MyFoo: BaseFoo {
public typealias FooBar = <#type#>
public typealias FooBar = MyBar
}
这似乎表明 MyBar
不是满足 FooBar
的正确类型,但它显然是一个 DataHolder
,正如所要求的那样。 这是怎么回事,我该如何解决?
当我尝试使用 Swift 3 进行编译时,我对此有了一些了解,这只需要很少的更改。现在,我收到两个错误:
public class MyFoo: BaseFoo { // Type 'MyFoo' does not conform to protocol 'BaseFoo'
public typealias FooBar = MyBar // Protocol 'MyBar' can only be used as a generic constraint because it has Self or associated type requirements
}
啊哈!现在这是我习惯处理的错误。所以,我把它作为通用参数放在 class 声明中:
public class MyFoo<_MyBar: MyBar>: BaseFoo {
public typealias FooBar = _MyBar
}
现在它编译得很好!将该修复程序带回 Swift 4 会得到相同的结果;现在它编译得很好。
所以问题是MyBar
过于泛化,不能直接作为类型使用,需要通过泛型参数进行抽象。