(如果有人可以提出更好的标题,请做)
以下代码无法使用错误Type 'ObserverClass' does not conform to protocol 'Observer'
进行编译,并且编译器通过声明var object: ObservedObject
来建议修复。
class ObservedObject {}
class ObservedObjectSubclass: ObservedObject {}
protocol Observer {
var object: ObservedObject { get }
}
class ObserverClass: Observer { // Type 'ObserverClass' does not conform to protocol 'Observer'
// suggested:
// var object: ObservedObject
var object: ObservedObjectSubclass = ObservedObjectSubclass()
}
我看到它的方式 - ObservedObjectSubclass
ObservedObject
,因此保证object
属性的类型为ObservedObject
协议。
(如果使用协议一致性而不是子类化,则同样如此)
protocol ObservedObjectProtocol {}
protocol Observer {
var object: ObservedObjectProtocol { get }
}
class ObservedObject: ObservedObjectProtocol {}
class ObserverClass: Observer { // same error
var object: ObservedObject = ObservedObject()
}
为什么编译器不开心?它是当前的限制,还是编译器实际上是正确的,并且存在一些逻辑约束?
答案 0 :(得分:3)
当您在协议中定义变量并为其分配类型时,这将是一个具体类型,因此在符合协议时您无法将其更改为该类型的子类。在符合类中声明的变量的类型必须与协议中声明的类型相同,它不能是协变(与继承相关)类型。
您可以通过为associatedType
协议创建Observer
来修复第二个错误,该协议继承自ObserverObject
,然后您可以将object
定义为与ObserverClass
相同的类型你的相关类型。然后,您可以让object
拥有ObservedObjectSubclass
类型的媒体class ObservedObject {}
class ObservedObjectSubclass: ObservedObject {}
protocol Observer {
associatedtype ObjectSubclass: ObservedObject
var object:ObjectSubclass { get }
}
class ObserverClass: Observer {
var object = ObservedObjectSubclass()
}
。
fun getPage() { val page: Page = WebClient().getPage("http://htmlunit.sourceforge.net") }