代码之家  ›  专栏  ›  技术社区  ›  Mercato

为什么协议默认值必须通过Swift中的扩展来实现?

  •  1
  • Mercato  · 技术社区  · 7 年前

    在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 @objc 因此使其无法用于结构/枚举(它们不是基于引用的值)?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Thomas    7 年前

    这个 @optional 指令是纯Objective-C指令,尚未翻译成Swift。这并不意味着你不能在Swift中使用它,但你必须先用he将你的Swift代码暴露给Objective-C @objc 属性

    为了回答您的第一个问题,协议在此定义而不是实现:

    协议定义了方法、属性和其他需求的蓝图[…]

    然后,该协议可以被类、结构或枚举采用,以提供这些需求的实际实现

    这个 纸质协议

    • 结论

    引言、章节和结论包含的内容取决于实现它们的人(作者),而不是协议。

    扩展为现有的类、结构、枚举或协议类型添加了新功能。这包括扩展您无法访问原始源代码的类型的能力。

    因此,扩展一个协议(这是允许的)可以为您添加新的功能,并由此提供定义方法的默认实现。这样做将成为Swift的唯一替代方案

    更新:

    虽然在Switch中为协议函数提供默认实现确实使其成为“可选的”,但这与使用 @可选 Objective-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)