[英]Swift Protocols: Custom Property Setter Crash because of Recursive loop
Swift:由于无限循环,自定义属性设置器崩溃
public protocol RequestType {
var parameters: AnyObject? { get set }
}
public extension RequestType {
public var parameters: AnyObject? {
get { return nil }
set { parameters = newValue }
}
public printParameters() {
print(parameters)
}
}
用法:
class HTTPBinRequest: RequestType { }
let request = HTTPBinRequest()
request.parameters = ["name" : "Rahul"]
request.printParameters()
它崩溃,因为它被卡在递归循环中。
但是,当我在类中声明该属性并将设置器保留为空时,它就可以正常工作。
class HTTPBinRequest: RequestType {
public var parameters: AnyObject?
}
public extension RequestType {
public var parameters: AnyObject? {
get { return nil }
set {}
}
public printParameters() {
print(parameters)
}
}
let request = HTTPBinRequest()
request.parameters = ["name" : "Rahul"]
谁能建议我如何解决这个更好的方法。
似乎您正在尝试在协议扩展中创建存储的属性 。 你不能那样做。 您只能在协议扩展中创建计算的属性 。
这是一个存储的属性:
class A {
var value: Int? // Stored property
}
这是一个计算属性:
class B {
var someString: String? // Stored property
var value: Int? { // Computed property
get { return Int(someString) }
set { someString = "\(newValue)" }
}
}
计算属性无法设置自身-如果您尝试设置该属性,它将创建您遇到的递归循环。 但是它可以做其他事情,例如设置类的其他存储属性,如上面的示例所示,它接受Int
作为新值,然后将其存储为String
。 永远不会存储Int
值本身。 当您检索Int
值时,每次访问它时,它都会从someString
计算得出。
如果您尝试将其作为协议来执行,则可以将计算属性放到协议中,而不要放到存储属性中:
protocol BProtocol {
var someString: String? { get set }
var value: Int? { get set }
}
extenstion BProtocol {
var value: Int? {
get { return Int(someString) }
set { someString = "\(newValue)" }
}
}
但是然后您仍然需要在类中定义存储的属性:
class B: BProtocol {
var someString: String?
}
但是您无需定义value
属性。 class B
将从BProtocol
扩展继承BProtocol
。
因此,对该问题的简短回答是,在您的类中创建存储的属性,而不是在协议扩展中创建。
编辑:
根据评论,也许您需要使用两层协议。 第一个协议列出了不使用parameters
属性的对象的要求:
protocol BaseProtocol {
var someStuff: String? { get set }
}
protocol BaseProtocolWithParameters: BaseProtocol {
var parameters: AnyObject? { get set }
}
我之所以这样说是因为,通常来说,具有要求用户创建从未使用过的属性的协议的协议是不好的设计。 如果某些对象永远不会使用parameters
,那么这些对象就不需要符合它们不需要的协议要求。 它们可以符合BaseProtocol
。 实际上确实需要使用对象parameters
能够符合BaseProtocolWithParameters
从继承BaseProtocol
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.