为什么默认情况下将Swift协议兼容值视为值类型?

问题描述 投票:0回答:2

我有一个协议,仅描述一个接口。

protocol SampleProtocol {
var message: String? { get set }}

为什么编译器总是将符合的值/对象视为值类型?

示例示例,

 // 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
ios swift swift-protocols
2个回答
0
投票

它不会创建该对象的副本。在两个调用中,它是同一对象–如果将print(Unmanaged.passUnretained(sampleValue as AnyObject).toOpaque())放入didSet中,您将看到地址相同。编译器不知道它在处理值类型还是引用类型。如果您将class关键字放在协议声明中,如下所示:

protocol SampleProtocol: class { ... }

didSet将被调用一次,因为编译器知道它是引用类型,因此不会重新分配引用。我猜生成的不同的setter取决于属性的类型


0
投票

您的协议SampleProtocol可以由classstruct采纳。 Swift会使用值类型的行为,该行为是限制性更强的类型,直到您告诉它该协议仅由class引用类型使用。

将协议更改为此以获取引用类型的行为:

protocol SampleProtocol: class {
    var message: String? { get set }
}

很好奇。 The Swift 5.1 Programming Guide - Class-Only Protocols建议使用AnyObject编写它:

protocol SampleProtocol: AnyObject {
    var message: String? { get set }
}

两者都做。

© www.soinside.com 2019 - 2024. All rights reserved.