让我们说我有一个实现了美丽主题观察者模式的课程。 (这是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术语&#34;委托&#34;大致相当于设计模式概念&#34;观察者&#34;。)
上面的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,一个包含实现Subject所需的所有代码和数据的类,在通用的Delegate类型上进行模板化,并在任何我们想让其他类充当Subject的地方继承它。相当简单。
协议,协议扩展和泛型似乎拥有这种代码重用所需的一些机制,但我无法解决如何实现它。
帮助?
答案 0 :(得分:0)
您可以使用协议继承和泛型从某些基本协议派生。
每个新委托都将从父类继承:
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> { }