为什么默认情况下将 Swift 符合协议的值视为值类型?
Why Swift protocol conforming values are treated as Value types by default?
我有一个协议,它只描述了一个接口。
protocol SampleProtocol {
var message: String? { get set }}
为什么编译器总是将符合要求的 value/object 视为值类型?
示例,
// Protocol value usage
import Foundation
protocol SampleProtocol {
var message: String? { get set }
}
final class SampleObject: SampleProtocol {
var message: String?
}
final class Controller {
var sampleValue: SampleProtocol! {
didSet {
print("New value has been set")
}
}
}
let controller = Controller()
controller.sampleValue = AlphaObject() // Correctly prints "New value has been set"
controller.sampleValue.message = "New message" // Prints again "New value has been set", like for value types
您的协议 SampleProtocol
可能会被 class
或 struct
采用。 Swift 正在使用值类型的行为,它是限制性更强的类型,直到您告诉它该协议将仅由 class
引用类型使用。
将对 AnyObject
的一致性添加到您的协议中以获得引用类型行为:
protocol SampleProtocol: AnyObject {
var message: String? { get set }
}
有关详细信息,请参阅 The Swift 5.1 Programming Guide - Class-Only Protocols。
指南注释:
Use a class-only protocol when the behavior defined by that protocol’s
requirements assumes or requires that a conforming type has reference
semantics rather than value semantics.
历史记录:使用class
关键字:
在 Swift 4.0 之前,这是使用 class
关键字编写的:
protocol SampleProtocol: class {
var message: String? { get set }
}
这暂时仍然有效,但它目前只是 AnyObject
的类型别名,可能会在 Swift 的更高版本中删除。
它不会创建对象的副本。在两个调用中它是同一个对象——如果你把 print(Unmanaged.passUnretained(sampleValue as AnyObject).toOpaque())
放在 didSet 中你会看到地址是相同的。编译器不知道它正在处理值类型或引用类型。如果你像这样在协议声明中放置一个 class 关键字:
protocol SampleProtocol: class { ... }
didSet 将被调用一次,因为编译器知道它是引用类型并且不会重新分配引用。
我想生成的不同设置器取决于 属性
的类型
我有一个协议,它只描述了一个接口。
protocol SampleProtocol {
var message: String? { get set }}
为什么编译器总是将符合要求的 value/object 视为值类型?
示例,
// Protocol value usage
import Foundation
protocol SampleProtocol {
var message: String? { get set }
}
final class SampleObject: SampleProtocol {
var message: String?
}
final class Controller {
var sampleValue: SampleProtocol! {
didSet {
print("New value has been set")
}
}
}
let controller = Controller()
controller.sampleValue = AlphaObject() // Correctly prints "New value has been set"
controller.sampleValue.message = "New message" // Prints again "New value has been set", like for value types
您的协议 SampleProtocol
可能会被 class
或 struct
采用。 Swift 正在使用值类型的行为,它是限制性更强的类型,直到您告诉它该协议将仅由 class
引用类型使用。
将对 AnyObject
的一致性添加到您的协议中以获得引用类型行为:
protocol SampleProtocol: AnyObject {
var message: String? { get set }
}
有关详细信息,请参阅 The Swift 5.1 Programming Guide - Class-Only Protocols。
指南注释:
Use a class-only protocol when the behavior defined by that protocol’s requirements assumes or requires that a conforming type has reference semantics rather than value semantics.
历史记录:使用class
关键字:
在 Swift 4.0 之前,这是使用 class
关键字编写的:
protocol SampleProtocol: class {
var message: String? { get set }
}
这暂时仍然有效,但它目前只是 AnyObject
的类型别名,可能会在 Swift 的更高版本中删除。
它不会创建对象的副本。在两个调用中它是同一个对象——如果你把 print(Unmanaged.passUnretained(sampleValue as AnyObject).toOpaque())
放在 didSet 中你会看到地址是相同的。编译器不知道它正在处理值类型或引用类型。如果你像这样在协议声明中放置一个 class 关键字:
protocol SampleProtocol: class { ... }
didSet 将被调用一次,因为编译器知道它是引用类型并且不会重新分配引用。 我想生成的不同设置器取决于 属性
的类型