为什么我不能在 Swift 中使用 let in 协议?

Why I can't use let in protocol in Swift?

我对 Swift 中关于 var 关键字 { get set } 的使用的协议有疑问。

来自Apple documentation

If a protocol requires a property to be gettable and settable, that property requirement cannot be fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it is valid for the property to be also settable if this is useful for your own code.

Property requirements are always declared as variable properties, prefixed with the var keyword. Gettable and settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }.

我不明白为什么我不能使用let。一个只有 get 的协议中的 var 不仅仅是一个 let?

像这样:

protocol someProtocol 
{
   var someProperty: String { get }
}

不只是:

protocol someProtocol 
{
   let someProperty: String
}

我错过了什么?

"A var in a protocol with only get isn't just a let?" 否。A let表示常数。但这里不是这种情况。考虑以下因素:

protocol SomeProtocol {
    var someProperty: String { get }
}

class SomeClass : SomeProtocol {

    var someProperty: String = ""

    func cla () {
        someProperty = "asd"
    }
}

let someInstance = SomeClass()

print(someInstance.someProperty) // outputs ""
someInstance.cla()
print(someInstance.someProperty) // outputs "asd"

该协议指定了符合要求的 class 向外部显示的内容 - 一些 String 类型的 属性 命名为 someProperty,您至少可以 得到。

如果协议指定 { get },您的 class 可以选择通过 let someProperty: String = "" 遵守,但同样可以通过上述代码选择遵守。另一方面,如果协议指定 { get set },则您不能在实现中使用 let,但也必须使其可设置。

协议不能简单地定义一个值必须是常量——也不应该,这是一个实现细节,必须由实现它的 class / 结构来处理(或决定) .

区别在于

protocol MyProtocol {
    let someProperty: String
}

这毫无意义 — 协议不应该规定 如何 someProperty 是 defined/stored,只有 那个 它可以作为 属性 使用。它可以是计算的或存储的 属性,但这是由实施者决定的,而不是协议本身。

protocol MyProtocol {
    var someProperty: String { get }  // abstract interface
}

struct MyStruct: MyProtocol {
    let someProperty: String  // concrete implementation: stored property
}

struct OtherStruct: MyProtocol {
    let i: Int
    var someProperty: String { return "\(i)" }  // concrete implementation: computed property
}

这是完全允许的!

我认为协议可以要求结构具有某些东西,但不能限制结构或对象的功能。这不应该阻止你做你可能想在代码中做的事情,例如在协议中使用 var 并且在实现中使用 let 是可以接受的。

protocol MyProtocol {
    var trythis: Int { get }
}

struct MyStructure: MyProtocol {
    let trythis: Int
}

let 声明的 属性 在幕后被认为是 read-only。出于这个原因,协议可以通过将 属性 设置为只读来要求它是一个常量。可以使用一些 Objc 运行时函数 property_getAttributes.

来验证此推论
protocol SomeProtocol {
    var someTypeProperty: Int { get }
}

struct Foo: SomeProtocol {
    let someTypeProperty: Int
}