2016-12-15 12 views
3

私は、このように美しい被験者 - 観察者パターンを実装するクラスを持っているとしましょう。 (これはスウィフト3である;。スウィフト2は、本質的には異なるないだろう)Swiftで一般的な被験者の実装を書く

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() } 
    } 
} 

(。私はとほぼ同等のデザインパターンの概念に慣用スウィフト用語「デリゲート」「オブザーバー」を取っている)

上記

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? 
} 

は今、私はDelegateに類似した別のデリゲートプロトコルでSubjectに類似した別のクラスを作成したいです。どのように私はすでに新しいクラスのSubjectのために書いた実装を使用するのですか?

答えは、コードをコピーして貼り付けることです。良い答えではありません。

C++では、Subjectを実装するために必要なすべてのコードとデータを含むクラスで、汎用のDelegate型にテンプレート化された真のmixinを作成し、他のクラスをa件名。かなり簡単です。

プロトコル、プロトコル拡張、およびジェネリックスには、この種のコード再利用に必要な機械がいくつかあるようですが、それを達成する方法はありません。

ヘルプ?

+0

私は誤解しているかもしれませんが、あなたの新しいクラスの 'Subject'から継承できないのでしょうか? – sdasdadas

+0

@sdasdadas新しいクラスのペア、 'NewSubject'と' NewDelegate'が必要だとします。問題は、 'NewDelegate'が' NewDelegate'を新しいデリゲート型にするよう 'Subject'を継承するにはどうすればいいのですか?例えば' eachDelegate() 'は' NewDelegate'を取る関数を取るでしょうか? – OldPeculier

答えて

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> { } 
+1

さて、私はそれがうまくいきたいです。しかし、プロトコルを使用してSwiftのジェネリックをインスタンス化することはできません。その結果、 'DelegateA'の新しいプロトコルタイプで動作できるように、' SubjectA'を継承することはできません。 SubjectAクラスのインスタンスを作成するには、具体的な型(プロトコル 'DelegateA'の実装)を使用する必要があります。そしてオブザーバープロトコルを持つサブジェクトクラスを持つ目的を破ってしまいました。 http://stackoverflow.com/q/33503602/358475を参照してください。 – OldPeculier

+0

@OldPeculier私はまだ理解していないのが怖いです。インスタンス化するときは、何かが具体的な型でなければなりません。私は完全に理解するには、あまりにも抽象的すぎるかもしれないと思う。 'NewSubject'と' NewDelegate'実装の例を教えてください。誰かがそれを訂正することができるように私は私の答えをしばらく残しておきます。 – sdasdadas

+1

@OldPeculierああ、私はもうちょっと時間があったことを理解している。私は拡張がそれを回避するだろうと思ったが、問題は、あなたが一般的な議論に従うためにプロトコルを使用することができないという事実にだけあると思われる。私はもっ​​と助けてくれることを願っています! – sdasdadas

関連する問題