簡體   English   中英

為什么默認情況下將符合 Swift 協議的值視為值類型?

[英]Why Swift protocol conforming values are treated as Value types by default?

我有一個協議,它只描述了一個接口。

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

您的協議SampleProtocol可以被classstruct Swift 正在使用值類型的行為,這是更嚴格的類型,直到您告訴它該協議將僅由class引用類型使用。

AnyObject一致性添加到您的協議中以獲取引用類型行為:

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

有關更多詳細信息,請參閱The Swift 5.1 Programming Guide - Class-Only Protocols

該指南指出:

當該協議的要求定義的行為假定或要求符合類型具有引用語義而不是值語義時,使用僅類協議。


歷史記錄:使用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 將被調用一次,因為編譯器知道它是一個引用類型並且不會重新分配引用。 我猜生成的不同 setter 取決於屬性類型

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM