有人可以告诉我为什么当Swift仅用于访问对象(协议)以设置其中一个属性时,为什么要调用属性的setter?第一个例子显示了如果我没有将间接对象声明为可设置的错误:
protocol AProtocol {
var name: String { get set }
}
class AnImplementation: AProtocol {
var name = ""
}
class AParent {
var test = AnImplementation()
}
class AChild {
var parent: AParent!
var test: AProtocol {
get { return parent.test }
// Note: Not settable
}
}
var parent = AParent()
var child = AChild()
child.parent = parent
child.test.name = "Hello world!" // Error: Cannot assign to property : 'test' is a get-only property
print(child.test.name)
如果我给它一个setter,它会编译并运行但它会调用setter:
protocol AProtocol {
var name: String { get set }
}
class AnImplementation: AProtocol {
var name = ""
}
class AParent {
var test = AnImplementation()
}
class AChild {
var parent: AParent!
var test: AProtocol {
get { return parent.test }
set(newTest) { print("Shouldn't be here!") }
}
}
var parent = AParent()
var child = AChild()
child.parent = parent
child.test.name = "Hello world!"
print(child.test.name)
输出是:
Shouldn't be here!
Hello world!
我不确定我在这里不理解什么。我想我可以给它一个空的二传手,但我想了解它的原因。
非常感谢任何信息!
答案 0 :(得分:2)
将您的协议声明更改为:
protocol AProtocol:class {
var name: String { get set }
}
否则,默认情况下它将被视为值类型。更改值类型的属性将替换值类型实例(如setter观察者所示)。如果引用是let
引用,则无法执行此操作。
答案 1 :(得分:2)
这可能是因为编译器不知道AChild.test
是类还是值类型。使用类没有问题,但是分配给name
的值类型也会创建对test
的赋值(值复制行为)。将APProtocol
标记为class
协议将解决问题。
要扩展,当编译器不确定test
是值还是类类型时,它将使用以下重写child.test.name = "Hello world!"
:
var tmp = child.test
tmp.test = "Hello world!"
child.test = tmp
因为它适用于类和值类型。