事実上同一のさまざまなオブジェクトをモデル化しようとしているとしましょう。唯一の違いはクラス変数です。ボイラープレートクラスを1つ作成し、特定の変数を使用してコンストラクターを呼び出すだけ、または本質的に同一のクラスを多数(この場合は100以上)作成し、それらのクラス変数(変更されない)をハードコーディングするほうがいいですか?
明確にするために:
明確に言うと、私の言語(Python)は私が知っているインターフェイスをサポートしていません。他の同様の質問のいくつかは、それを推奨する回答を得ているようです。私にとって理にかなっていると思われるもう1つのオプションは、各フィールドとメソッドを使用して基本クラスを作成してから、一意の値を含む一意の子クラスの束を作成することです。
すべての子クラスを作成するための作業量は私にとって重要ではありません-テキストファイル(すべての一意の値を持つ)をすばやく解析し、すべてのクラスを.pyファイルにすばやく書き込むことができるプログラムを作成しました。簡単に。同じ理由で、将来的に変更を加えるのはかなり簡単です。
(やや)関連する質問
100以上のほぼ同一のクラスはクレイジーです。クラスは組織構造です。バリエーションがほとんどない数十個あるのは役に立たないようです。それは専門化しすぎです。
共有情報を定義するルックアップテーブルを共有する単一のクラスが必要なようです。何かのようなもの:
from collections import namedtuple
Lang = namedtuple('Lang', 'style points creator')
LANG_FORM = {
'Python': Lang('dynamic', 84, 'Guido van Rossum'),
'Java': Lang('static', 65, 'James Gosling'),
# ...
'Pascal': Lang('static', 33, 'Niklaus Wirth')
}
class Protean(object):
def __init__(self, name, form):
self.name = name
self.form = form
self.lang = LANG_FORM[form] # optional
# methods here
ここでLANG_FORM
は、グローバル変数(準定数)にすることも、クラス変数にすることもできます。どちらの方法でも、各インスタンスは基本的に、共有情報(クラス変数と呼ばれるもの)へのポインターを取得します。各インスタンスでそれを記憶するのではなく、必要なときにいつでもLANG_FORM
にインデックスを付ける場合は、厳密にそれを必要としません。
各インスタンスがそのフォーム/種類/準クラスに基づいてそれ自体を表現するようにしたい場合は、__repr__
メソッドを追加します。
def __repr__(self):
classname = self.__class__.__name__
return "{0}-{1}({2!r}, {3})".format(classname, self.form, self.name, self.lang.points)
次に:
p = Protean('CPython', 'Python')
print p
収量:
Protean-Python('CPython', 84)
動作がすべてのクラスで同じであり、それらすべてに変更する理由が同じである場合、おそらくサブクラスはまったくありません。
これはインスタンス化と構成の問題です。クラスの使用法にのみ影響し、構造には影響しません。つまり、基本的には、クラスの使用とその保守におけるトレードオフについて話しているのです。
クラスの生成に使用するようなデータソースからオブジェクトをインスタンス化するのが簡単な場合は、なぜそうしないのですか?コンストラクターが覚えやすい、または調べやすい引数を3つだけ取る場合、なぜサブクラスなのですか?これほど多くのクラスを作成する理由はありません。
一方、クラスの生成は、何らかの理由で(予想に反して)状況が変化した場合に基本クラスとジェネレーターを保守する必要があるため、保守が困難になる可能性があります。
サブクラスを選択する理由は1つしか考えられません。それは、APIが大幅にシンプルになり、コードが理解しやすくなる場合です。たとえば、プログラマーによってクラスが非常に頻繁にインスタンス化され、データソースからフェッチされるデータの覚えにくい修飾子ではなく、クラス名を覚えるほうが簡単な場合です。または、修飾子を使用してデータを取得できず、プログラマーがクラスをインスタンス化するために多くの値を検索または計算する必要がある場合。 IMHOは、設定より規約のようなものであり、実際にはAPIの拡張機能であることがわかります。特に、プログラマーが値を検索する必要がある場合にサブクラスが値を検索する自然な場所である場合はそうです。ただし、多くの場合、人間が簡単に操作できるようにデータソース形式を調整することもできます。
サブレーザーを生成するもう1つの理由は、予想に反して、少なくとも一部のサブレーザーで強化された動作が必要になることに気付いた場合です。
明確に言うと、私の言語(Python)は私が知っているインターフェイスをサポートしていません。他の同様の質問のいくつかは、それを推奨する回答を得ているようです。
これは、動的に型指定された言語はインターフェースを必要としないためです。モース使用 ダックタイピング 。