public extension UIView { open func doStuff() {...} }
当我尝试在当前项目模块中的子类中重写此方法时
class ConcreteView : UIView { override open func doStuff() {...} }
我收到一个错误:
Overriding non-open instance method outside of its defining module
作为一种解决方法,我在同一模块中声明了另一个类,其中声明了扩展并在那里覆盖了所需的方法
public class CustomView: UIView { override open func doStuff() {...} }
并在主模块中将此类设置为我的类的超类
class ConcreteView : CustomView
所以只有在此之后我才能覆盖该方法.
它看起来真的像swift3中的一个错误,但也许我已经省略了为什么它以这种方式工作的一些理解?
解决方法
public extension UIView { open func doStuff() {...} }
有一个有效的访问级别“公共”,因为扩展名是
公开的.因此,它不能在子类中重写.
请注意,Xcode警告
warning: declaring instance method in PUBLIC extension
并且警告文本应该是(见下文)
warning: declaring OPEN instance method in PUBLIC extension
extension UIView { open func doStuff() {...} }
现在扩展的访问级别为“open”(继承自开放类UIView)
并且doStuff的有效访问级别是“开放的”,它可以是子类.
更长的回答:
Access Control在Swift参考中
说明
… you can mark an extension with an explicit access-level modifier … to set a new
default access level for all members defined within the extension. This new default
can still be overridden within the extension for individual type members.
但实际上您只能将扩展中的类型成员限制为相同
或较低的访问权限.不幸的是,我找不到明确的参考
事实上在文档中.
SE-0117 Allow distinguishing between public access and public overridability
说明
For example,the true access level of a type member is computed as the minimum of the
true access level of the type and the declared access level of the member. If the class
is public but the member is open,the true access level is public.
但没有解释这如何适用于扩展.
检查可以在编译器源代码中看到
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))
请注意,选择中缺少“打开”级别,这就是它缺失的原因
warning: declaring instance method in PUBLIC extension