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

Posted

技术标签:

【中文标题】为啥我不能在 Swift 中使用 let in 协议?【英文标题】:Why I can't use let in protocol in Swift?为什么我不能在 Swift 中使用 let in 协议? 【发布时间】:2016-03-26 22:48:03 【问题描述】:

我对 Swift 中关于 varkeywords get set 的使用的协议有疑问。

来自Apple documentation:

如果协议要求属性是可获取和可设置的,那么 常量存储属性不能满足属性要求 或只读计算属性。如果协议只需要一个 属性是可获取的,任何类型都可以满足要求 的属性,并且该属性也可以设置是有效的,如果 这对您自己的代码很有用。

属性要求总是声明为变量属性, 以 var 关键字为前缀。可获取和可设置的属性是 通过在类型声明后写 get set 来表示,并且 可获取的属性由 get 表示。

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

类似这样的:

protocol someProtocol 

   var someProperty: String  get 

这不仅仅是:

protocol someProtocol 

   let someProperty: String

我错过了什么?

【问题讨论】:

一个 gettable 属性仍然可以改变值 - 协议实现者总是可以返回不同的值,协议调用者根本无法设置它们。另一方面,let 定义一个常数。只能设置一次,不能有不同的值。 @pvg,你为什么不把这个作为答案发布? 是的,这是正确的答案。 @AntonBronnikov 对简单问题的回答通常会以谁能打出最冗长、最难理解的东西而告终。对于小事,更容易评论。还有,懒惰。 @pvg,我明白你的意思。一个人应该是正确的。 【参考方案1】:

“只有 get 的协议中的 var 不只是 let 吗?” 不,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"

协议指定了符合的类向外部显示的内容 - 一些名为 somePropertyString 类型的属性,您可以至少获得。

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

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

【讨论】:

回首过去,它是如此简单明了,在协议中只允许使用函数(然后是属性),但我总是更喜欢提出并解决任何疑问;现在使用 get set 一如既往的清晰,再次感谢! 协议不能简单地定义一个值必须是常数——也不应该是常数 为什么不呢?为什么 Apple 不提供更多的粒度并允许同时定义 let 和 var 属性?或者您是说,虽然 Apple 可以选择我所说的,但他们选择在实施级别提供灵活性【参考方案2】:

区别在于

protocol MyProtocol 
    let someProperty: String

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

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

这是完全允许的!

【讨论】:

协议不应该规定someProperty 的定义/存储方式 协议是否定义变量名称/类型/是否必须可设置?为什么 Apple 不提供更细的粒度并允许同时定义 let 和 var 属性?【参考方案3】:

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

protocol MyProtocol 
    var trythis: Int  get 


struct MyStructure: MyProtocol 
    let trythis: Int

【讨论】:

【参考方案4】:

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

protocol SomeProtocol 
    var someTypeProperty: Int  get 


struct Foo: SomeProtocol 
    let someTypeProperty: Int

【讨论】:

以上是关于为啥我不能在 Swift 中使用 let in 协议?的主要内容,如果未能解决你的问题,请参考以下文章

Swift: let 未初始化,但 var 已初始化。为啥? [复制]

为啥 Swift 的大于或小于运算符不能比较可选项,而相等运算符可以呢?

为啥不能在 ngFor 中使用 var 而不是 let

Swift语法注意点

为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]

为啥 for..of / for..in 循环可以使用 const 而普通的 for 循环在 JS 中只能使用 let 或 var 作为其变量? [复制]