【问题标题】:Why does swift hide default implementation for restricted protocols?为什么 swift 隐藏受限协议的默认实现?
【发布时间】:2019-09-11 11:19:18
【问题描述】:

我有一个声明如下的协议:

protocol RefreshableView where Self: UIView {
    func reload()
}

它的默认实现如下:

extension RefreshableView {
    func reload() {
        print("Default implementation")
    }
}

然后,如果我声明 UIView 的另一个(空)扩展符合此协议,我会收到编译时错误,指出 UIView 不符合协议。

extension UIView: RefreshableView {}

从我的角度来看,这不应该是一种情况,因为提供了默认实现。但是,如果我从协议声明中删除 where 语句(对可以符合协议的类的限制),一切都会按预期工作。消除此错误的另一种选择是在默认扩展声明旁边给出相同的where 语句,但这感觉是多余的,因为我已经让编译器知道该协议适用于狭窄的受众。这种行为有解释吗?

【问题讨论】:

  • protocol … where Self: … 是相当新的语法,所以还没有做好
  • @user28434 它没有被广泛使用,但至少从 swift 3 开始就已经存在。很可能它与扩展程序的 where 声明一样古老。
  • 必须是 Swift 错误。现在,您可以在扩展名上添加与 extension RefreshableView where Self: UIView 相同的 where 子句。
  • 确实感觉像是一个可能的错误,但也不清楚您要在这里表达什么。有了这三个,RefreshableView 和 UIView 完全是同一类型。每个 UIView 都是一个 RefreshableView,每个 RefreshableView 都必须是一个 UIView。这感觉像是编译器可能(无意中?)防止的错误。 reload() 的这种“默认”实现恰好成为 UIView 的扩展。

标签: ios swift swift-protocols swift-extensions


【解决方案1】:

你的意思是这不能编译:

protocol RefreshableView where Self: UIView {
    func reload()
}
extension RefreshableView {
    func reload() {
        print("Default implementation")
    }
}
extension UIView: RefreshableView {
}

正如 Rob Napier 在评论中指出的那样,这是一件很奇怪的事情,因为如果 UIView 本身 将采用 RefreshableView,那么协议的用途是什么?协议的原始声明意味着只有 UIView 子类 可以采用 RefreshableView,所以编译器期望的是会发生这样的事情:

protocol RefreshableView where Self: UIView {
    func reload()
}
extension RefreshableView {
    func reload() {
        print("Default implementation")
    }
}
class MyView: UIView {}
extension MyView: RefreshableView {
}

这是一个有用的真实案例,它编译得很好。

因此,您可以针对原始代码提交错误,但您必须承认这一点 是一个非常特殊的边缘案例;你在说一些事实上没人会说的话。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2018-01-22
    • 2015-09-22
    • 1970-01-01
    • 2021-04-30
    相关资源
    最近更新 更多