为啥我不能在 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 中关于 var 和 keywords 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"
协议指定了符合的类向外部显示的内容 - 一些名为 someProperty
的 String
类型的属性,您可以至少获得。
如果协议指定 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 的大于或小于运算符不能比较可选项,而相等运算符可以呢?
为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]
为啥 for..of / for..in 循环可以使用 const 而普通的 for 循环在 JS 中只能使用 let 或 var 作为其变量? [复制]