为什么这个基于协议的通用框架会被编译?

时间:2017-08-17 15:11:41

标签: swift swift-protocols

以下是我在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 {
}

但是编译器抱怨&#34; Type 'MyFoo' does not conform to protocol 'BaseFoo'&#34;。 Xcode问&#34;你想添加协议存根吗?&#34;当我点击&#34;修复&#34;时,它会这样做:

public class MyFoo: BaseFoo {
    public typealias FooBar = <#type#>

    public typealias FooBar = MyBar
}

这似乎表明MyBar不是满足FooBar的正确类型,但它显然是DataHolder,正如所需。 这里发生了什么,我该如何解决?

1 个答案:

答案 0 :(得分:0)

当我尝试使用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
}

啊哈!现在这是我以前用来处理的错误。所以,我把它作为通用参数放在类声明中:

public class MyFoo<_MyBar: MyBar>: BaseFoo {
    public typealias FooBar = _MyBar
}

现在编译得很好!将该修复程序带回Swift 4会产生相同的结果;现在它编译得很好。

所以问题是 MyBar过于通用而无法直接用作类型,需要通过通用参数进行抽象。