我在另一个模块(使用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中的一个错误,但也许我已经省略了为什么它以这种方式工作的理解?
答案 0 :(得分:12)
简答:
中的doStuff
方法
public extension UIView {
open func doStuff() {...}
}
的有效访问级别为“public”,因为扩展名为 公开的。因此,它不能在子类中重写。
请注意Xcode警告
警告:在PUBLIC扩展名中声明实例方法
并且警告文本应该(见下文)
警告:在PUBLIC扩展名中声明OPEN实例方法
要解决此问题,请删除扩展程序的public
访问修饰符:
extension UIView {
open func doStuff() {...}
}
现在,扩展程序的访问级别为“open”(继承自open class UIView
)
doStuff
的有效访问级别为“open”,可以是子类。
更长的回答:
Swift参考中的...您可以使用显式访问级别修饰符标记扩展名...以设置新的 扩展中定义的所有成员的默认访问级别。这个新的默认值 仍然可以在单个类型成员的扩展名中覆盖。
但实际上您只能将扩展中的类型成员限制为相同 或 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扩展名中声明实例方法