无法覆盖另一个模块swift中在类扩展中声明的open方法 [英] Cannot override open method declared in class extension in another module swift

查看:510
本文介绍了无法覆盖另一个模块swift中在类扩展中声明的open方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a class extension declared in another module (using pods) like this.

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

当我尝试在当前项目模块中的子类中覆盖此方法时

And when I try to override this method in subclass inside my current project module

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

我得到一个错误:

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

Overriding non-open instance method outside of its defining module

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

despite the method is actually marked as open

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

As a workaround I declared another class inside same module where extension is declared and overrided desired method there

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

并在主模块中将该类设置为我的类的超类

and set this class as super class for my class in main module

class ConcreteView : CustomView

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

so only after this I was able to override the method.

它看起来确实像是swift3中的错误,但也许我已经省略了对它为何如此工作的一些理解?

It really looks like a bug in swift3 but maybe I've omitted some understanding of why it works in that way?

推荐答案

简短答案:

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

具有有效的访问级别公共",因为扩展名是 标记为公开.因此,不能在子类中覆盖它.

has an effective access level "public" because the extension is marked public. Therefore it cannot be overridden in a subclass.

请注意,Xcode警告

Note that Xcode warns

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

warning: declaring instance method in PUBLIC extension

和警告文字应该是(请参见下文)

and the warning text should be (see below)

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

warning: declaring OPEN instance method in PUBLIC extension

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

To solve the problem, remove the public access modifier of the extension:

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

现在,扩展名具有访问级别开放"(从open class UIView继承) 并且doStuff的有效访问级别为开放",并且可以对其进行子类化.

Now the extension has the access level "open" (inherited from open class UIView) and the effective access level of doStuff is "open" and it can be subclassed.

更长的答案:

访问控制 指出

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

... 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.

,但实际上您只能将扩展名内的类型成员限制为相同 或访问权限.不幸的是,我对此没有明确的参考 文档中的事实.

but actually you can only restrict type members within the extension to the same or a lower access. Unfortunately, I could not find a definite reference for this fact in the documentation.

SE- 0117允许区分公共访问和公共可覆盖性 指出

例如,类型成员的真实访问级别被计算为 类型的真实访问级别和成员的声明访问级别.如果上课 是公开的,但成员是开放的,真正的访问权限是公开的.

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.

但没有解释这如何适用于扩展名.

but does not explain how this applies to extensions.

检查可以在编译器源代码中看到 TypeCheckAttr.cpp . 如果某项的访问级别较大,则包含项的访问级别 扩展然后 diag::access_control_ext_member_more 发出诊断消息:

The check can be seen in the compiler source code TypeCheckAttr.cpp. If the access level of an item is larger then the access level of the containing extension then the diag::access_control_ext_member_more diagnostic message is emitted:

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))

请注意,所选内容中缺少打开"级别,这就是为什么

Note that the "open" level is missing in the selection, and that is why it is missing in

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

warning: declaring instance method in PUBLIC extension

这篇关于无法覆盖另一个模块swift中在类扩展中声明的open方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆