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

wer*_*ver 6 ios swift swift2

我观看了"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",
// i.e. 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 T.x
    }
}

// And finally the property is successfully overridden (but why?).
print(Test<Z>().test()) // "zzz\n"
Run Code Online (Sandbox Code Playgroud)

这实际上是否意味着当在类中使用协议时static,协议(以及可能的默认实现)中的class关键字可以合法地替换为关键字?你知道有什么参考证实吗?

Bar*_*zyk 8

语言参考/声明我们知道以下内容.

功能声明

...

特殊方法

...

用类型,而不是一类型的实例相关联的方法必须标明的static声明修改为枚举和结构class声明修改的类.

static关键字(主要)用于枚举和结构,class关键字用于类.

还有这样一个说明:

键入变量属性

...

注意

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

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

协议怎么样?

协议方法声明

...

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

这里的文档声明我们应该在类或类扩展中实现协议时staticclass关键字声明替换协议声明中的关键字(这是原始问题的确切答案).

奖金

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

议定书宣言

...

默认情况下,符合协议的类型必须实现协议中声明的所有属性,方法和下标.也就是说,您可以使用optional声明修饰符标记这些协议成员声明,以指定它们的符合类型的实现是可选的.所述optional改性剂可以仅应用于标有协议objc属性.因此,只有类类型可以采用并符合包含可选成员要求的协议....

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

要仅限于将类协议用于类类型,请class通过将class关键字作为冒号后的继承协议列表中的第一项来标记具有该要求的协议....

但考虑staticclass关键词的适用性,它们都没有改变规则.