2017-01-22 6 views
1

代理/プロトコルパターンと通知を使用する代わりに、以下のコードのようなクラス間で通信できますか?このようなコード例は見たことがありません。しかし、なぜこれがうまくいくのか、うまくいかないのか不思議です。あなたがここにある何親クラスと子クラスの間の弱い参照

class Class1 { 

    var class2Obj: Class2 = Class2() 
    init() { 
     class2Obj.class1Obj = self 
    } 

    func class1Method() { 
     print("Parent") 
    } 
} 

class Class2 { 

    weak var class1Obj: Class1? 

    func class2Method() { 
     class1Obj.class1Method() 
    } 

} 
+0

はい、このように通信できます。しかし、デリゲート、ブロック、クロージャは、他の人がClass2が "メソッド"をコールバックすることを理解することがより理解できます。これは「ベストプラクティスは何か」の問題です: –

+0

@YunCHEN - はい、クロージャーパターンも使用できますが、クロージャーを使用することが「ベストプラクティス」であると主張する資格があります。単純なケースでは、クロージャーが便利かもしれませんが、より豊かなインターフェースでは、デリゲート・プロトコルのパターンはしばしば優れていますが、インターフェースの性質にもよりますが、 2つの密接に結合されたクラスのAnshuのパターンは最適ではありません。 – Rob

+0

@Rob、あなたと同意します。 –

答えて

3

デリゲートパターンです。代理人のプロパティは、より一般的なdelegateの名前ではなく、単にclass1Objと呼ばれます。ここでの重要な問題は、プロトコルを使用していないことです。その結果、これらの2つのクラスは「密接に結合」されています。つまり、Class2Class1の実装の詳細に大きく依存します。さらに、これら2つの緊密に結合されたクラスでは、のどのメソッドが必要かもしれないかはすぐには分かりません。 Class2の動作を壊すような変更を誤って行うことが容易になるため、Class1のメンテナンスが難しくなります。 Class1以外のクラスと組み合わせてClass2を使用することも難しくなります。

代わりに、Class2とそれを使用する必要があるかもしれない他のオブジェクトの間のコントラクトの性質を正確に明確にするプロトコルを宣言します。その結果、クラスは密接に結合されていない。すなわち、Class2は、問題のプロトコルへの適合に加えて、他のクラスについて何も知る必要がない。さらに、Class1を編集するときに、プロトコルに準拠するように宣言すると、必要なメソッドやプロパティを実装しなかったときに警告が表示されます。

このように、プロトコルは無視できない量の作業で、コードを維持しやすくします。また、Class2Class1以外のものを組み合わせて使用​​することもできます。

ボトムラインのプロトコルでは、保守が簡単で柔軟性の高いコードが生成され、隠された前提はありません。


デリゲートプロトコルのパターンを使用しない場合は、別の代替はClass1Class2が呼び出すことができることを、コードのブロックを提供するクロージャを、使用することです。あなたは二つのクラスの間の非常にシンプルなインターフェイスを持っているときに、二つのクラス間の豊富なインタフェース、この閉鎖パターンを持っている場合、デリゲートプロトコルパターンが有用であるが

class Class1 { 

    var class2Obj = Class2() 

    init() { 
     class2Obj.handler = { [weak self] in  // note `weak` reference which avoids strong reference cycle 
      self?.class1Method() 
     } 
    } 

    func class1Method() { 
     print("Parent") 
    } 
} 

class Class2 { 

    var handler: (() -> Void)? 

    func class2Method() { 
     handler?() 
    } 

} 

:だからあなたのような何かを行うことができます。

上記のより一般的な順列は、がClass2で開始する特定の要求とより直接関連している場合です。したがって、パラメータをClass2の適切なメソッドのクロージャにするだけです。さらに、あなたは頻繁にデータを渡すので、我々はオプションStringをバック渡していることを想像している:これらの閉鎖パターン

class Class1 { 

    var class2Obj = Class2() 

    func performClass2Method() { 
     class2Obj.class2Method { string in 
      guard let string = string else { return } 

      self.class1Method() 
     } 
    } 

    func class1Method() { 
     print("Parent") 
    } 
} 

class Class2 { 

    func class2Method(completionHandler: @escaping (String?) -> Void) { 
     // do something which creates `string` 

     // when done, call the closure, passing that `string` value back 

     completionHandler(string) 
    } 

} 

オブジェクト間の単純なインターフェースを行うための素晴らしい方法を、だけでなく、非常に緩く2つのクラスを保持します結合された(すなわち、Class2Class1に依存しません)、デリゲートパターンでプロトコルを使用するのとほとんど同じです。しかし、うまくいけば、上記の閉鎖の例は、リッチデリゲートプロトコルパターンの単純な代替案を示しているはずです。

関連する問題