web-dev-qa-db-ja.com

拡張と委任

私は Swift を使用していますが、 Extension および Delegation の概念について疑問に思っています。最近、私はこれら2つのコンセプトのどちらかが適用できるケースを見つけました。これは、「継承より合成」の原則を思い出させます。これは、「has-a」関係が「is-a」関係よりも優先される可能性があることを教えています。

特定のプロトコルに準拠するオブジェクトに依存する特定のタイプのオブジェクトであり、したがって拡張と委任の両方を使用できるケースに遭遇しました。

たとえば、UIViewのサブクラスに依存するUIViewControllerがあります。次のプロトコルを使用するとします。

protocol ViewInteraction {
  func interact()
}

このプロトコルは、UIViewサブクラス、たとえばInteractedViewに準拠します。そして、すべてのUIViewControllerがこのInteractedViewと対話する必要があるかもしれません。

これらのタイプの状況では、適切なデフォルトは何ですか-委任パターン、または拡張パターン?つまり、委任パターンを使用する必要があります-InteractedViewにそれを適合させ、UIViewControllerサブクラスにViewInteractionプロパティを操作させる-または、拡張パターンに従って拡張する必要がありますUIViewControllerViewInteractionプロトコルに準拠します(そしてInteractedViewを呼び出します)?

4
Vince

各View Controllerが異なるViewInteractionと対話する必要がある場合は、委譲が当然の選択です。すべてのView Controllerが同じ(グローバル)ViewInteractionと対話する必要がある場合、またはViewInteractionが特定のメソッドのパラメーターとして渡されてそこでのみ使用される場合は、拡張の方が適している場合があります。

覚えておくべきいくつかのこと。拡張メソッドは基本的にフリー関数を書くのと同じです。たとえば、以下を参照してください。

_class A {
}

extension A {
    func b() { print(self) }
}

func c(a: A) { print(a) }
_

myA.b()c(myA)の呼び出しの唯一の違いは構文です。誤解しないでください。私は拡張機能を軽視しようとはしていません。この構文の変更は、特にメソッドをチェーンしている場合、非常に大きな問題になる可能性があります。 (a.b().c(d)c(b(a), d)よりもはるかに読みやすいです)

これを念頭に置いておくと、意思決定に役立つでしょう。

3
Daniel T.