Swift允许协议属性和具有不相关类型的属性的符合对象之间发生名称冲突

时间:2019-01-25 21:27:36

标签: swift swift4

发现了一种情况,我希望发生名称和/或类型冲突,但是这种情况会不断发生并以某种方式编译。

当协议的版本具有扩展名中定义的默认值并且该对象通过(不相关的)扩展名符合协议时,具有某些属性的对象可以符合具有相同名称和不同类型的属性的协议。

请参见以下示例:

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,但在此处将其写出来以分享发现,并确定我是否遗漏了任何东西或做出有缺陷的假设。

1 个答案:

答案 0 :(得分:1)

实际上,这看起来像基于属性的重载。基本上,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"

现在,使用存储的属性无法进行上述操作,因为您只能使用一个存储名称,但是在协议扩展中会计算该属性,因此不会违反存储规则。