无法重写在另一个模块swift中的类扩展中声明的打开方法
我有一个类扩展声明在另一个模块(使用豆荚)这样的。
public extension UIView { open func doStuff() {...} }
当我尝试在我的当前项目模块中的子类中重写此方法
class ConcreteView : UIView { override open func doStuff() {...} }
我收到一个错误:
在其定义模块之外重写非开放实例方法
尽pipe方法实际上标记为打开
作为一种解决方法,我声明了另一个类在同一个模块中扩展声明和覆盖所需的方法
public class CustomView: UIView { override open func doStuff() {...} }
并将该类设置为主模块中的我的类的超类
class ConcreteView : CustomView
所以只有在这之后我才能够重写这个方法。
它看起来像swift中的一个bug,但也许我忽略了为什么它以这种方式工作的一些理解?
简短的回答:中的doStuff
方法
public extension UIView { open func doStuff() {...} }
有一个有效的访问级别“公共”,因为该扩展标记为公开的。 因此它不能在一个子类中重写。
请注意,Xcode警告
警告:在PUBLIC扩展中声明实例方法
和警告文本应该是 (见下文)
警告:在PUBLIC扩展中声明OPEN实例方法
要解决该问题,请删除扩展的public
访问修饰符:
extension UIView { open func doStuff() {...} }
现在扩展名的访问级别为“open”(inheritance自open class UIView
), doStuff
的有效访问级别为“open”,可以进行子类化。
较长的答案:
访问控制在Swift参考中指出
…您可以使用明确的访问级别修饰符标记扩展…为扩展中定义的所有成员设置新的默认访问级别。 这个新的默认值仍然可以在个别types成员的扩展名中被覆盖。
但实际上只能将扩展中的types成员限制为相同或较低的访问权限。 不幸的是,在文档中我找不到这个事实的明确参考。
SE-0117允许区分公共访问和公共可重写状态
例如,types成员的真实访问级别被计算为types的真实访问级别和成员的已声明访问级别的最小值。 如果class级是公开的,但是会员是开放的,则真实的访问级别是公开的。
但并没有解释如何适用于扩展。
该检查可以在编译器源代码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))
请注意,select中缺less“打开”级别,这就是为什么它缺less
警告:在PUBLIC扩展中声明实例方法