class
のいくつかの機能を使用するを持っているとしましょうdict
。以前はオブジェクトを内部で合成dict
し、外部からのアクセスを提供していましたが、最近、dict
必要な属性とメソッドを単純に継承して追加することを考えました。それは良い方法ですか、それとも構成に固執する必要がありますか?
4 に答える
継承は非常に頻繁に悪用されます。あなたのクラスが追加機能を備えた一般的な辞書として使用されることを意図していない限り、私は構成が進むべき道だと思います.
通常、転送呼び出しを保存することは、継承を選択する十分な理由にはなりません。
デザインパターンの本から:
クラス継承よりもオブジェクト合成を優先する
理想的には、再利用を実現するために新しいコンポーネントを作成する必要はありません。オブジェクト構成によって既存のコンポーネントを組み立てることで、必要なすべての機能を取得できるはずです。しかし、利用可能なコンポーネントのセットが実際には十分に豊富ではないため、これはめったにありません。継承による再利用により、古いコンポーネントで構成できる新しいコンポーネントを簡単に作成できます。したがって、継承とオブジェクトの構成は連携して機能します。
それにもかかわらず、私たちの経験では、設計者は継承を再利用手法として使いすぎており、オブジェクト構成に依存することで設計がより再利用可能 (かつ単純) になることがよくあります。」
どちらも良いですが、コードが少なくなるので(読み取り可能である限り常に良い)、継承することをお勧めします。
Pythonに飛び込むには、非常に関連性の高い例があります。
Python 2.2以前では、組み込みから直接サブクラス化することはできなかったため、compositionを使用する必要がありました。
class FileInfo(dict): "store file metadata" def __init__(self, filename=None): self["name"] = filename
- 最初の違いは、dictは組み込みのデータ型であり、いつでも使用できるため、UserDictモジュールをインポートする必要がないことです。2つ目は、UserDict.UserDictからではなく、dictから直接継承していることです。
- 3番目の違いは微妙ですが重要です。UserDictが内部で機能する方法の
__init__
ため、内部データ構造を適切に初期化するには、手動でメソッドを呼び出す必要があります。dict
このようには機能しません。ラッパーではなく、明示的な初期化は必要ありません。
isinstance(my_object, dict)
True または False を返す必要がありますか? 言い換えれば、オブジェクトの 1 つを を必要とするものに誤って渡してしまった場合、そのオブジェクトはdict
それを として使用しようとするべきdict
でしょうか? おそらくそうではないので、コンポジションを使用してください。
やろうとしていることのコストと範囲を実際に検討する必要があります。辞書のような動作が必要なため、from を継承するdict
のは手早く簡単ですが、クラスから作成されたオブジェクトがハッシュ不可になるなどの制限が生じがちです。
したがって、たとえば、オブジェクトをシリアル化 (つまり) する必要があるがpickle
、辞書のような動作も必要な場合は、明らかに直接継承することはできず、目的dict
の機能の部分を構成する必要があります。それを実現します。