假设我有一个类,它实现了一个漂亮的主题观察者模式。(这是Swift 3;Swift 2在本质上不会有什么不同。)

protocol Delegate : class
{
    func method()
}

class Subject
{
    private typealias WeakDelegate = WeakReference< Delegate >
    private var nextAvailableDelegateId = 0
    private var delegates = [ Int : WeakDelegate ]()

    @discardableResult
    public func addDelegate( _ delegate: Delegate ) -> Int
    {
        let id = nextAvailableDelegateId
        nextAvailableDelegateId += 1
        delegates[ id ] = WeakDelegate( value: delegate )
        return id
    }

    public func removeDelegate( _ idForDelegate: Int )
    {
        delegates.removeValue( forKey: idForDelegate )
    }

    fileprivate func eachDelegate( fn: (Delegate) -> Void )
    {
        for (key, weakDelegate) in delegates
        {
            // Has this weak delegate reference become nil?
            //
            guard let delegate = weakDelegate.value else
            {
                // Yes. Remove it.
                delegates.removeValue( forKey: key )
                continue
            }

            fn( delegate )
        }
    }

    private func exampleNotifier()
    {
        eachDelegate{ $0.method() }
    }
}

(我将惯用的swift术语“委托”大致等同于设计模式概念“观察者”。)
上面的WeakReference类型并不是这个问题的一部分,但是如果你好奇的话:
public class WeakReference< T >
{
    public var value: T?
    {
        return abstractValue as? T
    }

    public init( value: T )
    {
        abstractValue = value as AnyObject
    }

    private weak var abstractValue: AnyObject?
}

现在,我想用另一个类似于Subject的委托协议创建另一个类似于Delegate的类。如何在新类中使用已经为Subject编写的实现?
一个答案是复制和粘贴代码。回答不好。
在C++中,我们可以创建一个真正的MIXIN,一个包含实现该主题所需的所有代码和数据的类,在泛型委托类型上模板化,并继承它,无论我们想把其他类动作作为主题。相当微不足道。
协议、协议扩展和泛型似乎具有这种代码重用所必需的一些机制,但我无法解决如何实现它。
帮助?

最佳答案

您可以使用协议继承和泛型从一些基本协议派生。
每个新委托都将从父类继承:

protocol Delegate: class {

    func method()
}

protocol DelegateA: Delegate { }

protocol DelegateB: Delegate { }

您的父主题类可以使用符合父协议的泛型实现。
class Subject<T: Delegate> {

    private typealias WeakDelegate = WeakReference<T>
    private var nextAvailableDelegateId = 0
    private var delegates = [Int: WeakDelegate]()

    @discardableResult
    public func addDelegate(_ delegate: T) -> Int {
        let id = nextAvailableDelegateId
        nextAvailableDelegateId += 1
        delegates[id] = WeakDelegate( value: delegate )
        return id
    }

    public func removeDelegate(_ idForDelegate: Int) {
        delegates.removeValue(forKey: idForDelegate)
    }

    fileprivate func eachDelegate( fn: (T) -> Void ) {
        for (key, weakDelegate) in delegates {
            // Has this weak delegate reference become nil?
            guard let delegate = weakDelegate.value else {
                // Yes. Remove it.
                delegates.removeValue( forKey: key )
                continue
            }
            fn( delegate )
        }
    }

    private func exampleNotifier() {
        eachDelegate{ $0.method() }
    }
}

每个新主题都可以实例化为符合您的子委托的通用主题。
class SubjectA<T: DelegateA>: Subject<T> { }

class SubjectB<T: DelegateB>: Subject<T> { }

关于swift - 在Swift中编写一个共同的主题 - 观察者实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41170451/

10-12 00:16
查看更多