一尘不染

Swift 2协议扩展未正确调用重写的方法

swift

使用默认实现的Swift
2协议扩展遇到了一个问题。基本要点是,我已经提供了协议方法的默认实现,我将在实现该协议的类中重写该方法。该协议扩展方法是从基类中调用的,然后该基类将调用在派生类中已重写的方法。结果是未调用重写的方法。

我试图将问题提炼到最小的游乐场,以说明以下问题。

protocol CommonTrait: class {
    func commonBehavior() -> String
}

extension CommonTrait {
    func commonBehavior() -> String {
        return "from protocol extension"
    }
}

class CommonThing {
    func say() -> String {
        return "override this"
    }
}

class ParentClass: CommonThing, CommonTrait {
    override func say() -> String {
        return commonBehavior()
    }
}

class AnotherParentClass: CommonThing, CommonTrait {
    override func say() -> String {
        return commonBehavior()
    }
}

class ChildClass: ParentClass {
    override func say() -> String {
        return super.say()
        // it works if it calls `commonBehavior` here and not call `super.say()`, but I don't want to do that as there are things in the base class I don't want to have to duplicate here.
    }
    func commonBehavior() -> String {
        return "from child class"
    }
}

let child = ChildClass()
child.say() // want to see "from child class" but it's "from protocol extension”

阅读 182

收藏
2020-07-07

共1个答案

一尘不染

不幸的是,协议还没有这样的动态行为。

但是,您可以(在类的帮助下)通过commonBehavior()在中实现ParentClass并在中进行覆盖来做到这一点ChildClass。您还需要一个CommonThing或另一个类来遵循,CommonTrait然后才是的超类ParentClass

class CommonThing: CommonTrait {
    func say() -> String {
        return "override this"
    }
}

class ParentClass: CommonThing {
    func commonBehavior() -> String {
        // calling the protocol extension indirectly from the superclass
        return (self as CommonThing).commonBehavior()
    }

    override func say() -> String {
        // if called from ChildClass the overridden function gets called instead
        return commonBehavior()
    }
}

class AnotherParentClass: CommonThing {
    override func say() -> String {
        return commonBehavior()
    }
}

class ChildClass: ParentClass {
    override func say() -> String {
        return super.say()
    }

    // explicitly override the function
    override func commonBehavior() -> String {
        return "from child class"
    }
}
let parent = ParentClass()
parentClass.say()          // "from protocol extension"
let child = ChildClass()
child.say()                // "from child class"

由于这只是您问题的一个简短解决方案,我希望它适合您的项目。

2020-07-07