2017-08-14 71 views
0

在斯威夫特,你不能在协议定义本身定义的功能或属性的默认实现,即:为什么必须通过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而不是基于引用)时才可实现?

编辑:添加在扩展示例

+1

有没有真正的理由在协议声明的默认实现AREN不可能;差别仅仅是语法。因此,我认为这不是执行的重中之重(如果有的话)。它[包含在泛型声明中](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#default-implementations-in-protocols-),所以可能会被认为是该语言的更高版本。 – Hamish

回答

0

@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) 
+0

所以这个现象是由Swift(因此Chris Lattner)如何定义协议和扩展,而不是一些隐藏的实现细节带来的? Swift的文档确实强调了扩展默认v @optional是不一样的 - (通过扩展提供的默认实现的协议要求不同于可选的协议要求)。我个人觉得不得不延长这样的事情有点笨重,也许是因为我太习惯Java的界面风格了 – Mercato

+0

@Mercato我更新了我的答案,可选和扩展默认的主要区别在于它太长了评论! – Thomas

相关问题