无法覆盖另一个模块swift中类扩展中声明的open方法

时间:2016-12-05 20:44:58

标签: ios swift swift3

我在另一个模块(使用pod)中声明了一个类扩展名。

public extension UIView {
  open func doStuff() {...}
}

当我尝试在当前项目模块

中的子类中覆盖此方法时
class ConcreteView : UIView {
  override open func doStuff() {...}
}

我收到错误:

  

在其定义模块之外覆盖非开放实例方法

尽管该方法实际上标记为打开

作为一种解决方法,我在同一模块中声明了另一个类,其中声明了扩展并且覆盖了所需的方法

public class CustomView: UIView {
  override open func doStuff() {...}
}

并将此类设置为主模块

中我的类的超类
class ConcreteView : CustomView

所以只有在此之后我才能覆盖该方法。

它真的看起来像swift3中的一个错误,但也许我已经省略了为什么它以这种方式工作的理解?

1 个答案:

答案 0 :(得分:12)

简答:

中的doStuff方法
public extension UIView {
  open func doStuff() {...}
}

的有效访问级别为“public”,因为扩展名为 公开的。因此,它不能在子类中重写。

请注意Xcode警告

  

警告:在PUBLIC扩展名中声明实例方法

并且警告文本应该(见下文)

  

警告:在PUBLIC扩展名中声明OPEN实例方法

要解决此问题,请删除扩展程序的public访问修饰符:

extension UIView {
  open func doStuff() {...}
}

现在,扩展程序的访问级别为“open”(继承自open class UIViewdoStuff的有效访问级别为“open”,可以是子类。

更长的回答:

Swift参考中的

Access Control 说明

  

...您可以使用显式访问级别修饰符标记扩展名...以设置新的   扩展中定义的所有成员的默认访问级别。这个新的默认值   仍然可以在单个类型成员的扩展名中覆盖。

但实际上您只能将扩展中的类型成员限制为相同 或 lower 访问权限。不幸的是,我找不到明确的参考 事实上在文档中。

SE-0117 Allow distinguishing between public access and public overridability 说明

  

例如,类型成员的真实访问级别计算为最小值   类型的真实访问级别和成员的声明访问级别。如果上课   是公开的,但会员是开放的,真正的访问级别是公开的。

但没有解释这是如何适用于扩展程序的。

可以在编译器源代码中看到该检查 TypeCheckAttr.cpp。 如果项目的访问级别大于包含的访问级别 延伸然后 diag::access_control_ext_member_more 发出诊断消息:

WARNING(access_control_ext_member_more,none,
    "declaring %select{PRIVATE|a fileprivate|an internal|a public}0 %1 in "
    "%select{a private|a fileprivate|an internal|PUBLIC}2 extension",
    (Accessibility, DescriptiveDeclKind, Accessibility))

请注意,选择中缺少“打开”级别,这就是

中缺少的原因
  

警告:在PUBLIC扩展名中声明实例方法