如何将复杂的抽象类移植到swift?

时间:2016-12-26 06:23:17

标签: swift

我脑子里有一个抽象类,我不能在swift中实现它的几个功能,所以我使用C ++来表达我的想法:

template <class T>
class Swapping {
public:
    void swap() { _foregroundIndex = backgroundIndex() }
    virtual void cleanup() = 0;
    T* foreground() { return _buffer[foregroundIndex()]; }
    T* background() { return _buffer[backgroundIndex()]; }
    void setForeground(T* foreground) { _buffer[foregroundIndex()] = foreground; }
    void setBackground(T* background) { _buffer[backgroundIndex()] = background; }
private: 
    short foregroundIndex() { return _foregroundIndex; } 
    short backgroundIndex() { return _foregroundIndex ^ 1; }
    short _foregroundIndex = 0;
    T* _buffer[2] = {NULL, NULL};
}

主要矛盾是

  1. 纯虚方法cleanup()要求所有子类明确地实现它(可以使用protocol快速实现)
  2. 实例变量_foregroundIndex具有初始值(不能使用protocol实现)
  3. 实例变量_foregroundIndex仅限于private无法使用protocol实现)
  4. 另一方面,如果我使用class代替protocol,那么我无法保证覆盖cleanup()方法。

    有人可能建议将虚拟方法放在protocol中,将实例变量放在class中。这可能有效但不是令人满足的。

    P.S。 Objective-C不是Swift。任何objc_runtime相关的解决方法都不是首选。

1 个答案:

答案 0 :(得分:2)

有一个明显的解决方案,我经常看到,但肯定不会让你满意的是:

func cleanup() {
    fatalError("You must override cleanup()")
}

然后你可以尝试使用extension来扩展协议的默认实现,但扩展不允许存储属性,所以你很可能需要一些外部对象或其他魔法你当然也不喜欢。

正如我在评论中所述,您可能需要重新考虑您的设计。我不知道你真正打算做什么,但也许这样的事情对你有用:

class Swapper<T> {
    private var foregroundIndex = 0
    private var backgroundIndex: Int {
        return foregroundIndex ^ 1
    }
    private var buffer: [T?] = [nil, nil]

    private let cleanupHandler: () -> ()

    init(cleanupHandler: @escaping () -> ()) {
        self.cleanupHandler = cleanupHandler
    }

    func cleanup() {
        cleanupHandler()
    }

    var foreground: T? {
        get {
            return buffer[foregroundIndex]
        }
        set {
            buffer[foregroundIndex] = newValue
        }
    }
    var background: T? {
        get {
            return buffer[backgroundIndex]
        }
        set {
            buffer[backgroundIndex] = newValue
        }
    }

    func swap() {
        foregroundIndex = backgroundIndex
    }
}

这对我来说更有意义,因为这允许任何类型与任何清理处理程序交换,而不必每次都对类进行子类化。