Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift 4中,扩展的声明还不能被覆盖_Ios_Swift_Swift4_Extension Methods - Fatal编程技术网

Ios 在Swift 4中,扩展的声明还不能被覆盖

Ios 在Swift 4中,扩展的声明还不能被覆盖,ios,swift,swift4,extension-methods,Ios,Swift,Swift4,Extension Methods,我最近将代码迁移到了Swift 4。我在扩展方面面临一个问题,即: 扩展的声明还不能被重写 我已经读过多篇文章对这个问题进行了重新分类。但它们中没有一个符合以下描述的情况: class BaseCell: UITableViewCell { //Some code here... } extension BaseCell { func isValid() -> String? { //Some code here... } } class

我最近将代码迁移到了Swift 4。我在扩展方面面临一个问题,即:

扩展的声明还不能被重写

我已经读过多篇文章对这个问题进行了重新分类。但它们中没有一个符合以下描述的情况:

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...
    }
}
据苹果公司称

扩展可以向类型添加新功能,但不能覆盖现有功能

但是在上面的场景中,我没有覆盖扩展中的方法
isValid()
。它在
SampleCell
类定义本身中被重写。尽管如此,它还是给出了错误

但是在上面的场景中,我并没有覆盖扩展中的方法
isValid()

isValid
在扩展名中声明

该错误几乎表明,如果函数以这种方式声明,它不能被重写


该语句对扩展名中的和扩展名中的都有效,我认为这是不言自明的。 来自扩展的声明还不能被覆盖

您正试图
重写
函数
func isValid()->String?
,该函数是在
BaseCell
扩展中声明的,而不是
BaseCell
类本身

很明显,您不能覆盖在扩展中声明的内容


希望有帮助。

在Swift 3中,如果扩展属于从Objective-C()派生的类,则可以重写扩展函数,但我想现在在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编译类的方式以及它处理Objective-C类和函数的新方式有关。在Swift 3中,如果一个类是从NSObject派生的,那么该类中的所有变量和函数都将使用Objective-C的动态命名和查找约定。这种方法抑制了Swift优化代码、提高代码性能和大小的能力

为了克服这些惩罚,在Swift 4中,只有显式标记为
@objc
的变量和函数才能得到Objective-C处理,其他所有内容都使用标准Swift约定:因此产生了错误

有了这些知识,问题的解决方案是将扩展中希望重写的函数标记为
@objc
,然后在子类中重写该函数,但请记住包含
@objc
标记,以便在运行时调用代码

警告:如果您忘记在
覆盖
中包含
@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

你不想用
extension BaseCell
而不是
extension SampleCell
?@4kman我错了。它是BaseCell而不是SampleCell。“但是在上面的场景中,我没有覆盖extension中的方法
isValid()
。,是的,您将尝试重写它。此语句对“from extension”和“in extension”都有效吗?是的。无论如何,在扩展中重写函数没有多大意义,因为这应该通过子类化来完成。实际上,为了更好地理解和可读性,我已经基于功能创建了一个类的多个扩展。现在我得到了这个错误。要解决这个问题,我必须将所有代码移到一个块中。这背后的原因是什么?为什么不允许这样做?这是一个很好的观点,在Swift 3中被支持,但在Swift 4中不再支持。那些将Swift 3项目迁移到Swift 4的人可能会看到这个问题,并首先思考他们的代码是如何编译的。只是Swift 4减少了
@objc
推断。如果您声明函数
@objc
,它将像以前一样工作。