Ios Swift:协议扩展中的静态属性可以被覆盖,但为什么?
我观看并阅读了相关文档,但我仍然认为以下示例代码中存在冲突(请在操场上尝试)Ios Swift:协议扩展中的静态属性可以被覆盖,但为什么?,ios,swift,swift2,Ios,Swift,Swift2,我观看并阅读了相关文档,但我仍然认为以下示例代码中存在冲突(请在操场上尝试) 协议X{ //重要的部分是“静态”关键字 静态变量x:String{get} } 扩展X{ //这里又是“静态” 静态变量x:String{ 得到{ 返回“xxx” } } } //现在我要在一个类中使用协议,但是 //在类中,“静态”类似于“最终类”, //也就是说,不能被覆盖,对吗? //但我更希望能覆盖这个属性, //所以我将尝试使用“class”关键字。 //它会破坏程序吗?(剧透:没有!) Y类:X类{ //
协议X{
//重要的部分是“静态”关键字
静态变量x:String{get}
}
扩展X{
//这里又是“静态”
静态变量x:String{
得到{
返回“xxx”
}
}
}
//现在我要在一个类中使用协议,但是
//在类中,“静态”类似于“最终类”,
//也就是说,不能被覆盖,对吗?
//但我更希望能覆盖这个属性,
//所以我将尝试使用“class”关键字。
//它会破坏程序吗?(剧透:没有!)
Y类:X类{
//这里我们可以使用“class”关键字(但为什么?)。
类var x:String{
得到{
返回“yyy”
}
}
}
Z类:Y类{
重写类var x:String{
得到{
返回“zzz”
}
}
}
课堂测试{
func test()->字符串{
返回T.x
}
}
//最后,该属性被成功覆盖(但为什么?)。
打印(Test().Test())/“zzz\n”
这实际上是否意味着当协议在类中使用时,协议中的静态
关键字(以及可能的默认实现)可以合法地替换为类
关键字?你知道有任何证明这一点的参考资料吗?从中我们知道以下内容
函数声明
特殊类型的方法
与类型而非类型实例关联的方法必须使用枚举和结构的静态
声明修饰符或类的类
声明修饰符进行标记
也就是说,static
关键字(主要)用于枚举和结构,class
关键字用于类
还有这样一个注释:
类型变量属性
注
在类声明中,关键字static
与使用class
和final
声明修饰符标记声明具有相同的效果
也就是说,static
关键字实际上可以在类声明中使用,并且将意味着最终类
那么协议呢?
协议方法声明
要在协议声明中声明类或静态方法需求,请使用static
声明修饰符标记方法声明。实现此方法的类使用class
修饰符声明该方法。实现它的结构必须使用static
声明修饰符声明方法。如果在扩展中实现该方法,则在扩展类时使用类
修饰符,在扩展结构时使用静态
修饰符
这里的文档说明,在类或类扩展中实现协议时,我们应该将协议声明中的static
关键字替换为class
关键字(这是对原始问题的准确答案)
奖金
有两种情况下,协议采用仅限于类。第一个(也是最不明确的)是当协议包含可选成员时:
议定书声明
默认情况下,符合协议的类型必须实现协议中声明的所有属性、方法和下标。也就是说,您可以使用optional
声明修饰符标记这些协议成员声明,以指定它们通过一致类型的实现是可选的。可选
修饰符只能应用于标有objc
属性的协议。因此,只有类类型可以采用并符合包含可选成员要求的协议
第二段(明确;下一段):
要将协议的采用仅限于类类型,请将class
关键字作为继承协议列表中冒号后的第一项,用class
要求标记协议
但是考虑到静态
和类
关键字的适用性,它们都没有改变规则。从文档中可以明显看出这一点。更有趣的问题是,在类中使用协议时,用类
关键字替换原来的静态
是否合法?对不起,这同样很简单(因为文档中确实提到了它们),但没有一个词说明如何静态
(这可能意味着最终类
)在协议中,可以在实现此类协议的类中用类
(这可能意味着“忘记最终版
”)替换。这合法吗?文档中有描述吗?我认为答案是“是的,它是合法的(我们已经检查过了),而不是,它没有在文档中描述”:(它可能意味着最终的,但正如我们所看到的,在这里它不是Tyes。但是你同意文档在这一点上不够明确吗?(目前这种知识只能通过实验提取)我把文档理解为只有final类
防止子类重写,static
本身不这样做。它强制只在类内实现class
关键字,这并不意味着它是final
。
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"