将成员键入为另一协议的Swift协议
我正在试验Swift协议,我遇到了一些有趣的事情。有很多变通方法,但是有人能解释下面的错误吗将成员键入为另一协议的Swift协议,swift,generics,protocols,associated-types,Swift,Generics,Protocols,Associated Types,我正在试验Swift协议,我遇到了一些有趣的事情。有很多变通方法,但是有人能解释下面的错误吗 protocol UserRenderable { var name : String { get } } protocol PostRenderable { var title: String { get } var author: UserRenderable { get } } struct User { let id: String let name
protocol UserRenderable {
var name : String { get }
}
protocol PostRenderable {
var title: String { get }
var author: UserRenderable { get }
}
struct User {
let id: String
let name : String
}
struct Post {
let id: String
let title: String
let author: User
}
extension User : UserRenderable {}
extension Post: PostRenderable {}
上述代码(将其放在操场上或其他地方)将抛出编译错误:
协议需要类型为“UserRenderable”的属性“author”;是否要添加存根?var作者:UserRenderable{get}
原因是什么?您的
Post
结构对于作者有一个非常特殊的类型。协议规定可后期渲染的内容需要有可用户渲染的作者。虽然所有的User
s都是UserRenderable
,但并非所有的UserRenderable
项都是User
。因此,您应该将author
的类型更改为UserRenderable
,而不是User
最好的解决方案不是关联类型。看起来有一个更整洁的选择(来自):
没有真正的理由不可能做到这一点,只读
属性要求可以是协变的,如返回一个ConformsToB
属性类型为ProtocolB的实例是完全合法的
斯威夫特只是目前不支持它。为了做到这一点
编译器必须在协议见证之间生成一个thunk
表1和一致性实施,以执行必要的
类型转换。例如,ConformsToB实例需要
被装箱在存在容器中以便作为ProtocolB键入
(调用者无法做到这一点,因为它可能不知道
任何关于正在调用的实现的信息)
但同样,编译器没有理由不能这样做
这个
事实证明,你可以用好的typelias
诱使编译器执行你的命令,而不必写一声巨响。此代码编译时没有问题:
protocol UserRenderable {
var name : String { get }
}
protocol PostRenderable {
var title: String { get }
var author: UserRenderable { get }
}
struct User {
let id: String
let name : String
}
struct Post {
let id: String
let title: String
let author: User
}
extension User : UserRenderable {}
extension Post: PostRenderable {
typealias User = UserRenderable
}
@josh caswell,你知道为什么会这样吗?