发现了一个场景,我预计会发生名称和/或类型冲突,但它会以某种方式通过并编译。
当协议(protocol)的版本具有在扩展中定义的默认值并且对象通过(不相关的)扩展符合协议(protocol)时,具有某些属性的对象可以符合具有相同名称和不同类型的属性的协议(protocol)。
请看下面的例子:
import Foundation
protocol SomeProtocol {
var someProperty: Int { get }
}
extension SomeProtocol {
var someProperty: Int { return 3 }
}
struct Thing {
var someProperty = "string cheese"
}
extension Thing: SomeProtocol {}
let thing = Thing()
print(thing.someProperty) // string cheese
print(thing.someProperty as Int) // 3
请注意,在 Swift 中重载属性通常会导致编译时错误:
class Thing {
var what: Int { return 3 }
var what: String { return "three" }
}
错误内容如下:
**Untitled 8.swift:4:6: note: 'what' previously declared here
var what: Int { return 3 }**
很明显它表现为一个重载函数,但这种行为似乎不是故意的。
向 bugs.swift.org 提交了一张票,但将其写在此处以分享发现并查明我是否遗漏了任何内容或做出了任何有缺陷的假设。
最佳答案
实际上,这看起来像是基于属性的重载。基本上 Swift 允许这样的事情:
func compute() -> Int {
return 42
}
func compute() -> String {
return "Answer to the Ultimate Question of Life, the Universe, and Everything"
}
可以这样调用:
let number = compute() as Int // 42
let string = compute() as String // "Answer to the Ultimate Question of Life, the Universe, and Everything"
现在,上述情况对于存储属性是不可能的,因为您只能有一个存储名称,但是在协议(protocol)扩展中该属性是计算出来的,因此它不违反存储规则。
关于Swift 允许协议(protocol)属性和具有不相关类型属性的符合对象之间的名称冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54373010/