Swift 4 中还不能覆盖来自扩展的声明
Declarations from extensions cannot be overridden yet in Swift 4
我最近将我的代码迁移到了 Swift 4。我面临 extensions 的问题,即:
Declarations from extensions cannot be overridden yet
我已经阅读了多篇对这个问题进行重新评分的帖子。但是他们中的 none 接受了下面描述的场景:
class BaseCell: UITableViewCell
{
//Some code here...
}
extension BaseCell
{
func isValid() -> String?
{
//Some code here...
}
}
class SampleCell: BaseCell
{
//Some code here...
override func isValid() -> String? //ERROR..!!!
{
//Some code here...
}
}
根据 Apple 的说法,
Extensions can add new functionality to a type, but they cannot override existing functionality.
但是在上面的场景中,我并没有覆盖扩展中的方法isValid()
。它在 SampleCell
class 定义本身中被覆盖。仍然,它给出了错误。
But in the above scenario, I am not overriding the method isValid()
in an extension.
isValid
在 扩展 中声明。
错误基本上是说,如果以这种方式声明一个函数,它不能被覆盖。
该语句对来自扩展和在扩展中均有效。
我认为这是不言自明的。
声明 FROM 扩展还不能被覆盖
您正在尝试 override
在 BaseCell
的 extension
中声明的函数 func isValid() -> String?
,而不是 BaseCell
class本身。
它清楚地表明您不能覆盖在扩展中声明的内容。
希望对您有所帮助。
在 Swift 3 中,如果扩展是从 Objective-C (http://blog.flaviocaetano.com/post/this-is-how-to-override-extension-methods/) 派生的 class,您可以覆盖扩展的功能,但我想现在在 Swift 4 中是不可能的。你当然可以这样做:
protocol Validity {
func isValid() -> String?
}
class BaseCell: UITableViewCell, Validity {
}
extension Validity
{
func isValid() -> String? {
return "false"
}
}
class SampleCell: BaseCell {
func isValid() -> String? {
return "true"
}
}
let base = BaseCell()
base.isValid() // prints false
let sample = SampleCell()
sample.isValid() // prints true
在Swift中无效,但在Objective-C中无效。因此,如果您的方法签名允许它(没有 objc 禁止构造),您可以声明它 @objc func myMethod()
并在 Swift.
中自由覆盖它
我也有大量的 Swift 3 代码,它们使用这个老技巧来实现我想要的,所以当我转到 Swift 4 并开始出现这些错误时,我有点苦恼。别怕,有办法的。
此错误与 Swift 4 编译 classes 的方式以及它处理 Objective-C classes 和函数的新方式有关。在 Swift 3 下,如果 class 派生自 NSObject,那么 class 中的所有变量和函数都将使用 Objective-C 的动态命名和查找约定。这种方法抑制了 Swift 优化代码和提高代码性能和大小的能力。
为了克服这些惩罚,在 Swift 4 中,只有明确标记为 @objc
的变量和函数得到 Objective-C 处理,其他所有内容都使用标准 Swift 约定:因此错误。
有了这些知识,您的问题的解决方案是将您希望覆盖的扩展中的函数标记为 @objc
,然后在子 classes 中覆盖该函数,但请记住包含 @objc
标记,这样您的代码将在运行时被调用。
警告 这里有一个小问题:如果您忘记在 override
中包含 @objc
,编译器不会报错,但是您的代码缺少动态查找,因此在运行时永远不会被调用。
所以您的代码应该看起来像这样:
class BaseCell: UITableViewCell {
//Some code here...
}
extension BaseCell {
@objc func isValid() -> String? {
//Some code here...
}
}
class SampleCell: BaseCell {
//Some code here...
@objc override func isValid() -> String? {
//Some code here...
}
}
只要您 @objc
协议,您就可以覆盖扩展中的声明。在 Swift 4.2:
class BaseClass {}
class SubclassOfBaseClass: BaseClass {}
@objc protocol IsValidable {
func isValid() -> Bool
}
extension BaseClass: IsValidable {
func isValid() -> Bool { return false }
}
extension SubclassOfBaseClass {
override func isValid() -> Bool { return !super.isValid() }
}
BaseClass().isValid() // -> false
SubclassOfBaseClass().isValid() // -> true
我最近将我的代码迁移到了 Swift 4。我面临 extensions 的问题,即:
Declarations from extensions cannot be overridden yet
我已经阅读了多篇对这个问题进行重新评分的帖子。但是他们中的 none 接受了下面描述的场景:
class BaseCell: UITableViewCell
{
//Some code here...
}
extension BaseCell
{
func isValid() -> String?
{
//Some code here...
}
}
class SampleCell: BaseCell
{
//Some code here...
override func isValid() -> String? //ERROR..!!!
{
//Some code here...
}
}
根据 Apple 的说法,
Extensions can add new functionality to a type, but they cannot override existing functionality.
但是在上面的场景中,我并没有覆盖扩展中的方法isValid()
。它在 SampleCell
class 定义本身中被覆盖。仍然,它给出了错误。
But in the above scenario, I am not overriding the method
isValid()
in an extension.
isValid
在 扩展 中声明。
错误基本上是说,如果以这种方式声明一个函数,它不能被覆盖。
该语句对来自扩展和在扩展中均有效。
我认为这是不言自明的。 声明 FROM 扩展还不能被覆盖
您正在尝试 override
在 BaseCell
的 extension
中声明的函数 func isValid() -> String?
,而不是 BaseCell
class本身。
它清楚地表明您不能覆盖在扩展中声明的内容。
希望对您有所帮助。
在 Swift 3 中,如果扩展是从 Objective-C (http://blog.flaviocaetano.com/post/this-is-how-to-override-extension-methods/) 派生的 class,您可以覆盖扩展的功能,但我想现在在 Swift 4 中是不可能的。你当然可以这样做:
protocol Validity {
func isValid() -> String?
}
class BaseCell: UITableViewCell, Validity {
}
extension Validity
{
func isValid() -> String? {
return "false"
}
}
class SampleCell: BaseCell {
func isValid() -> String? {
return "true"
}
}
let base = BaseCell()
base.isValid() // prints false
let sample = SampleCell()
sample.isValid() // prints true
在Swift中无效,但在Objective-C中无效。因此,如果您的方法签名允许它(没有 objc 禁止构造),您可以声明它 @objc func myMethod()
并在 Swift.
我也有大量的 Swift 3 代码,它们使用这个老技巧来实现我想要的,所以当我转到 Swift 4 并开始出现这些错误时,我有点苦恼。别怕,有办法的。
此错误与 Swift 4 编译 classes 的方式以及它处理 Objective-C classes 和函数的新方式有关。在 Swift 3 下,如果 class 派生自 NSObject,那么 class 中的所有变量和函数都将使用 Objective-C 的动态命名和查找约定。这种方法抑制了 Swift 优化代码和提高代码性能和大小的能力。
为了克服这些惩罚,在 Swift 4 中,只有明确标记为 @objc
的变量和函数得到 Objective-C 处理,其他所有内容都使用标准 Swift 约定:因此错误。
有了这些知识,您的问题的解决方案是将您希望覆盖的扩展中的函数标记为 @objc
,然后在子 classes 中覆盖该函数,但请记住包含 @objc
标记,这样您的代码将在运行时被调用。
警告 这里有一个小问题:如果您忘记在 override
中包含 @objc
,编译器不会报错,但是您的代码缺少动态查找,因此在运行时永远不会被调用。
所以您的代码应该看起来像这样:
class BaseCell: UITableViewCell {
//Some code here...
}
extension BaseCell {
@objc func isValid() -> String? {
//Some code here...
}
}
class SampleCell: BaseCell {
//Some code here...
@objc override func isValid() -> String? {
//Some code here...
}
}
只要您 @objc
协议,您就可以覆盖扩展中的声明。在 Swift 4.2:
class BaseClass {}
class SubclassOfBaseClass: BaseClass {}
@objc protocol IsValidable {
func isValid() -> Bool
}
extension BaseClass: IsValidable {
func isValid() -> Bool { return false }
}
extension SubclassOfBaseClass {
override func isValid() -> Bool { return !super.isValid() }
}
BaseClass().isValid() // -> false
SubclassOfBaseClass().isValid() // -> true