Swift:协议扩展中的静态属性可以被覆盖,但为什么?

我看了“Swift中的面向协议的编程”并阅读了相关的文档,但是我仍然认为在下面的示例代码中存在冲突(在Playground中尝试)。

protocol X { // The important part is "static" keyword static var x: String { get } } extension X { // Here "static" again static var x: String { get { return "xxx" } } } // Now I'm going to use the protocol in a class, BUT // in classes "static" is like "final class", // ie CAN'T BE OVERRIDDEN, right? // But I'd prefer to have the ability to override that property, // so I'll try to use "class" keyword. // Will it break the program? (spoiler: no!) class Y: X { // Here we are allowed to use "class" keyword (but why?). class var x: String { get { return "yyy" } } } class Z: Y { override class var x: String { get { return "zzz" } } } class Test<T: X> { func test() -> String { return Tx } } // And finally the property is successfully overridden (but why?). print(Test<Z>().test()) // "zzz\n" 

这实际上是否意味着协议中的static关键字(和可能的默认实现)可以合法地用class关键字replaceclass使用的协议? 你知道任何参考证实吗?

从语言参考/声明我们知道以下。

函数声明

特殊的方法

与types相关联的方法而不是types的实例必须用枚举和结构static声明修饰符或class声明修饰符来标记。

static关键字是(主要)为枚举和结构和class关键字是类。

也有这样一个说明:

typesvariables属性

注意

在类声明中,关键字static与使用classfinal声明修饰符标记声明具有相同的效果。

static关键字实际上可以在类声明中使用,将意味着final class

那么协议呢?

协议方法声明

要在协议声明中声明类或静态方法要求,请使用static声明修饰符标记方法声明。 实现此方法的class使用class修饰符声明方法。 实现它的结构必须用static声明修饰符来声明方法。 如果要在扩展中实现该方法,请在扩展class使用class修饰符,如果扩展了结构,请使用static修饰符。

这里的文档声明,当在类或类扩展中实现协议时(这是对原始问题的确切答案),我们应该使用class关键字从协议声明中replacestatic关键字。

奖金

有两种情况下协议的采用将仅限于类。 第一个(也是最不明确的)是当协议包含optional成员时:

议定书声明

默认情况下,符合协议的types必须实现在协议中声明的所有属性,方法和下标。 也就是说,可以使用optional声明修饰符标记这些协议成员声明,​​以指定通过一致性types的实现是可选的。 optional修饰符只能应用于使用objc属性标记的协议。 因此,只有types可以采用并符合包含可选成员要求的协议 。 …

第二个(明确的;下一段):

要将协议限制为类types,可以通过将class关键字作为inheritance协议列表中的第一项写入冒号后面来标记具有class要求的协议 。 …

但是考虑到staticclass关键字的适用性,它们都不会改变规则。