首页 > 解决方案 > Swift 中的类绑定协议细化

问题描述

为什么这段代码会引发编译错误?

protocol P { var i: Int { get set } }
protocol ClassP: P, AnyObject {}
class C: ClassP { var i: Int = 0 }

let classP: ClassP = C()
classP.i = 1   //  Cannot assign to property: 'classP' is a 'let' constant

但是,如果我将AnyObject限制移至P

protocol P: AnyObject { var i: Int { get set } }
protocol ClassP: P {}
class C: ClassP { var i: Int = 0 }

let classP: ClassP = C()
classP.i = 1

请注意在两个示例classP中的类型为ClassP, 并且ClassP是类绑定的。但是编译器似乎注意到,只有当属性在本身已经是类绑定的协议中声明时,赋值才会针对类实例的属性(而不是结构实例)。的静态类型classP似乎被忽略了。为什么?

理想情况下P,它本身不应该是类绑定的,因为它很容易具有非类绑定的细化和符合类型。当然,在这些情况下,p.i = 1分配仅对 writeable 有效p。使用 let-const pp.i = 1仅当p已知是符合的实例时才有效(我认为在上面的示例中是正确的,因为已知类型是ClassP并且确实是类绑定的)。我如何在 Swift 中表达这一点?

标签: swiftprotocols

解决方案


不漂亮,但添加i作为ClassP沉默错误的要求:

protocol P { var i: Int { get set } }
protocol ClassP: P, AnyObject { var i: Int { get set }  }
class C: ClassP { var i: Int = 0 }

let classP: ClassP = C()
classP.i = 1

推荐阅读