父子协议关系和ObjC可用性

Cri*_*tik 9 protocols objective-c swift

我无法使用以下代码:

@objc protocol Child { }

@objc protocol Parent {
    var child: Child { get }
}

class ChildImpl: Child { 
    func doSomething() { }
}

class ParentImpl: Parent {
    let child = ChildImpl()

    // this would solve the problem, however can't access the ChildImpl members
    // that are not part of the protocol
    // let child: Child = ChildImpl()

    // as well as this, however maintaining two properties is an ugly hack
    // var child: Child { return childImpl }
    // private let childImpl = ChildImpl()
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误:

Playground执行失败:错误:Tests.playground:3:7:错误:类型'ParentImpl'不符合协议'Parent'类ParentImpl:Parent {^

Tests.playground:4:9:注意:候选人具有非匹配类型'ChildImpl'var child = ChildImpl()

基本上我有两个父子协议,以及两个实现这两个协议的类.但是,编译器抱怨说这ChildImpl不是一个Child,这不是真的.

如果我使用相关类型,我可以使错误消失 Parent

protocol Parent {
    associatedtype ChildType: Child
    var child: ChildType { get }
}
Run Code Online (Sandbox Code Playgroud)

但是,我需要将协议提供给Objective-C,并且还需要能够引用child作为实际的具体类型.

是否有一个解决方案,不涉及重写协议Objective-C,或不添加重复的属性声明只是为了避免这个问题?

Cri*_*tik 0

简短的回答是否定的,当前的设计不适用于当前的 Swift 语言。

原因是var child: Child { get }协议要求在幕后创建了一个存在容器,例如ExistentialContainer<Child>. 因此,任何符合协议的类型也必须声明相同类型的存在容器,而不是ExistentialContainer<Subtype>.

似乎存在容器不是协变的,因此暂时需要使用问题和其他答案中描述的解决方法。