你可以覆盖在扩展之间的Swift或不? (编译器看起来很困惑!)

前端之家收集整理的这篇文章主要介绍了你可以覆盖在扩展之间的Swift或不? (编译器看起来很困惑!)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在一个iOS应用程序在Swift(大部分是从Objective-C移动)。我使用Core Data并尝试使用扩展来向我的模型自动生成的类添加功能。我在Objective-C中很容易做到的一件事是在A类的类别中添加一个方法,并在B类(从A派生)中的类别中覆盖该方法,我希望在Swift中这样做。

有一段时间,我已经在我的项目中有以下代码(这只是一个例子),虽然我还没有使用的功能,编译器已经工作了很好编译这段代码

// From CellType.swift -- NOTE: Imports from Foundation and CoreData
@objc(CellType)
class CellType: NSManagedObject {
    @NSManaged var maxUses: NSNumber
    @NSManaged var useCount: NSNumber
    // Other properties removed for brevity
}


// From SwitchCellType.swift -- NOTE: Imports from Foundation and CoreData
@objc(SwitchCellType)
class SwitchCellType: CellType {
    @NSManaged var targetCellXIndex: NSNumber
    @NSManaged var targetCellYIndex: NSNumber
    @NSManaged var targetCellType: CellType
    // Other properties removed for brevity
}


// From CellTypeLogic.swift -- NOTE: Imports from Foundation and CoreData
extension CellType
{
    var typeLabel : String { get { return "Empty"; } }
    func isEqualToType(otherCellType : CellType) -> Bool
    {
        return (self.typeLabel == otherCellType.typeLabel &&
            self.maxUses.isEqualToNumber(otherCellType.maxUses) &&
            self.useCount.isEqualToNumber(otherCellType.useCount));
    }
    // Code removed for brevity
}


// From SwitchCellTypeLogic.swift -- NOTE: Imports from Foundation and CoreData
extension SwitchCellType    // YES,this compiles with the overrides!
{
    override var typeLabel : String { get { return "Switch"; } }
    override func isEqualToType(otherCellType : CellType) -> Bool
    {
        var answer = false;
        if let otherSwitchCellType = otherCellType as? SwitchCellType
        {
            answer = super.isEqualToType(otherCellType) &&
                self.targetCellXIndex.isEqualToNumber(otherSwitchCellType.targetCellXIndex) &&
                self.targetCellYIndex.isEqualToNumber(otherSwitchCellType.targetCellYIndex) &&
                self.targetCellType.isEqualToType(otherSwitchCellType.targetCellType);
        }
        return answer;
    }
    // Code removed for brevity
}

希望一些Swift专家在那里已经看到我的问题,但这里是我如何找到它:最近我试图添加类似的功能使用方法,有参数和/或返回值不是类型,但我开始得到错误:扩展中的声明无法覆盖。

为了探讨这个问题,我添加以下到我的一个swift文件,认为它会编译就好:

class A
{
}

class B : A
{
}

extension A
{
    var y : String { get { return "YinA"; } }
}

extension B
{
    override var  y : String { get { return "YinB"; } }  // Compiler error (see below) -- What??
}

令我吃惊的是,我收到了相同的编译器错误(扩展中的声明不能覆盖)。什么?但我已经使用了这种模式已经没有编译器错误

问题:
首先,是否有一些关于覆盖扩展的规则,在某些情况下它应该工作,但在其他情况下不是?第二(和更令人不安的)为什么看起来Swift编译器是如此不一致?我在这里失踪了什么?请帮助我恢复我对Swift的信心。

更新:

正如Martin R在正确答案中指出的,似乎你可以覆盖当前版本的Swift(1.1通过Xcode 6.1)的方法,只要它们(1)只涉及从NSObject派生的类和(2)不使用inout修饰符。下面是一些示例:

class A : NSObject { }

class B : A { }

class SubNSObject : NSObject {}
class NotSubbed {}
enum SomeEnum { case c1,c2; }

extension A
{
    var y : String { get { return "YinA"; } }
    func f() -> A { return A(); }
    func g(val: SubNSObject,test: Bool = false) { }

    func h(val: NotSubbed,test: Bool = false) { }
    func j(val: SomeEnum) { }
    func k(val: SubNSObject,inout test: Bool) { }
}

extension B 
{
    // THESE OVERIDES DO COMPILE:
    override var  y : String { get { return "YinB"; } }
    override func f() -> A { return A(); }
    override func g(val: SubNSObject,test: Bool) { }

    // THESE OVERIDES DO NOT COMPILE:
    //override func h(val: NotSubbed,test: Bool = false) { }
    //override func j(val: SomeEnum) { }
    //override func k(val: SubNSObject,inout test: Bool) { }

}
看起来重写的方法属性在一个扩展工程与
当前Swift(Swift 1.1 / Xcode 6.1)仅用于Objective-C兼容
方法属性

如果一个类派生自NSObject,那么它的所有成员都会自动可用
在Objective-C(如果可能,见下文)。所以用

class A : NSObject { }

您的示例代码按预期编译和工作。您的代码数据扩展覆盖
工作,因为NSManagedObject是NSObject的子类。

或者,可以对方法属性使用@objc属性

class A { }

class B : A { }

extension A
{
    @objc var y : String { get { return "YinA" } }
}

extension B
{
   @objc override var y : String { get { return "YinB" } }
}

在Objective-C中不能表示的方法不能用@objc标记并且不能在子类扩展中覆盖。这适用于例如具有enum类型的inout参数或参数的方法

猜你在找的Swift相关文章