为什么必须通过Swift中的扩展实现协议默认值?
在斯威夫特,你不能在协议定义本身定义的功能或属性的默认实现,即:为什么必须通过Swift中的扩展实现协议默认值?
protocol Container {
//These are fine
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get set }
subscript(i: Int) -> Item { get }
//These are not fine
var defaultValue: Int = 10
mutating func messWithCount(){
self.count *= 10
}
}
extension Container {
//This is fine though
mutating func messWithCount(){
self.count *= 10
}
}
但是你可以通过扩展这样做(尽管扩展不支持存储性能,它们支持的功能和计算的 - 虽然存储的财产问题可以是worked around)。
这背后的解释是什么?作为补充,optional func
的解释只有在我们将Protocol和func都标记为@objc
并因此使其不可用于Structs/Enums(基于Value而不是基于引用)时才可实现?
编辑:添加在扩展示例
的@optional
指令是一个Objective-C仅指示并没有被翻译成斯威夫特。这并不意味着你不能在Swift中使用它,但是你必须首先使用@objc
属性将Swift代码暴露给Objective-C。
请注意,暴露给Obj-C只会使协议可用于Swift和Obj-C中的类型,这不包括例如Structs,因为它们只在Swift中可用!
要回答你的第一个问题,协议在这里定义和没有实现:
协议定义的方法,属性,和其它要求的蓝图[...]
而且因此实现应该由符合它的类/ stuct/enum提供:
然后协议可以被类,结构或枚举采用来提供n实际执行这些要求
这个定义确实适用于我们在日常生活中使用的协议。举个例子的协议写一个文件:
的PaperProtocol限定了纸为具有以下非零变量的文档:
- 简介
- 章节
- 结论
引言,章节和结论包含的内容取决于实现它们的人(作者)而不是protoco湖
当我们在扩展的定义,我们可以看到,他们来这里是为了增加(实施)的新功能:
扩展添加新的功能,以现有的类,结构,枚举,或协议类型。这包括扩展您无法访问原始源代码的类型的功能。
因此,扩展一个协议(这是允许的)给你添加新功能的可能性,并在此给出一个定义方法的默认实现。这样做可以作为Swift替代上面讨论的@optional
指令。
UPDATE:
虽然给人一种默认实现在交换机的协议功能确实使“可选”,它是根本不一样的Objective-C中使用@optional
指令。
在Objective-C中,未实现的可选方法根本没有实现,因此调用它会导致崩溃,因为它不存在。因此,必须在调用它之前检查它是否存在,与Swift相反,使用扩展缺省值,因为缺省实现存在时可以安全地调用它。
中的OBJ-C可选会这样使用:
NSString *thisSegmentTitle;
// Verify that the optional method has been implemented
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
// Call it
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
} else {
// Do something as fallback
}
凡的SWIFT对应与扩展默认是:
let thisSegmentTitle = self.dataSource.titleForSegmentAtIndex(index)
有没有真正的理由在协议声明的默认实现AREN不可能;差别仅仅是语法。因此,我认为这不是执行的重中之重(如果有的话)。它[包含在泛型声明中](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#default-implementations-in-protocols-),所以可能会被认为是该语言的更高版本。 – Hamish