4

オブジェクト指向プログラミングの推奨原則の 1 つは、リスコフ置換原則です。サブクラスは、その基本クラスと同じように動作する必要があります (警告: これは、実際にはリスコフ原則の正しい説明ではありません: PS を参照してください)。 .

コンストラクターにも適用することをお勧めしますか? 私は主に Python とその__init__()メソッドを念頭に置いていますが、この質問は継承を使用するすべてのオブジェクト指向言語に当てはまります。

私がこの質問をしている理由は、サブクラスが 1 つまたは複数のクラスから継承して、いくつかの優れたデフォルトの動作を提供することが役立つ場合があるためです (Python での辞書からの継承のようobj['key']に、新しいクラスのオブジェクトに対して機能します)。ただし、サブクラスを辞書とまったく同じように使用できるようにすることは、常に自然または単純であるとは限りません。コンストラクターのパラメーターを特定のユーザー サブクラス (たとえば、一連のシリアル ポートを表すクラス) のみに関連付ける方がよい場合があります。辞書のように振る舞いたいかもしれませんports['usb1']USB ポート #1 など)。そのような状況への推奨されるアプローチは何ですか? 基本クラスのコンストラクターと完全に互換性のあるサブクラス コンストラクターを持ち、シンプルで使いやすいパラメーターを取るオブジェクト ファクトリ関数を介してインスタンスを生成しますか? または、基本クラスのコンストラクターにパラメーターのセットを直接渡すことができないクラス コンストラクターを単に作成しますが、ユーザーの観点からはどちらがより論理的でしょうか?

PS : 上記の Liskov の原則を誤解しました: 以下の Sven のコメントは、サブクラスのオブジェクトはスーパークラスのオブジェクトのように振る舞うべきであるという事実を指摘しています (サブクラス自体はスーパークラスのように振る舞う必要はありません; 特に、それらのコンストラクターには同じパラメーター [署名] を持つ)。

4

1 に答える 1

4

リクエストに応じて、以前のコメントを回答として投稿します。

リンクされたウィキペディアの記事で定義されている原則は、「S が T のサブタイプである場合、タイプ T のオブジェクトをタイプ S のオブジェクトに置き換えることができる」と書かれています。「サブクラスはその基本クラスと同じように動作する必要があります」とは書かれていません。この違いは、コンストラクターについて考えるときに重要です。ウィキペディアのバージョンでは、型自体ではなく、サブタイプのオブジェクトについてのみ説明しています。オブジェクトの場合、コンストラクターは既に呼び出されているため、原則はコンストラクターには適用されません。これは私がそれを適用する方法でもあり、標準ライブラリで適用されているように見える方法でもあります (例: defaultdictand dict)。

多重継承のコンストラクターは、おそらく言語に依存しない方法で議論することはできません。Python には 2 つのアプローチがあります。継承ダイアグラムにひし形パターンが含まれていて、すべてのコンストラクターが 1 回だけ呼び出されるようにする必要がある場合は、Raymond Hettinger の記事Python の考えられるスーパーsuper()の「実用的なアドバイス」セクションで説明されているパターンを使用して従う必要があります。ひし形がない場合 ( を含むものを除く)、すべての基本クラス コンストラクターに対して明示的な基本クラス呼び出しを使用することもできます。super()object

于 2012-01-24T01:02:08.697 に答える