3

クラス階層があるとしましょう。インスタンスに追加のパラメーターを提供することで、理論的には単一のクラスでその機能を維持できます。これが例です(非常に不自然ですが、シンプルにしたかったのです):

class Base:
  def __init__(self, a):
    self.a = a
  def f(self, x):
    raise NotImplemented # needs to be defined in subclass

class Mult(Base)
  def f(self, x):
    return self.a * x

class Add(Base):
  def f(self, x):
    return self.a + x

m = Mult(5)
a = Add(7)
m.f(10)
a.f(20)

上記のコードは、次のようにリファクタリングできます。

class Compute:
  def __init__(self, a, func):
    self.a = a
    self.func = func
  def f(self, x)
    return self.func(self.a, x)

m = Compute(5, operator.mult)
a = Compute(7, operator.add)

このばかげた例では、違いがないことは理解しています。ですから、私の言いたいことを理解するため以外に考えないでください。

実生活で遭遇するさまざまな状況でこの選択を行う際に、どのような要因を考慮する必要があるか知りたいですか? つまり、クラスとパラメーター化されたインスタンスを使用することの長所/短所は何ですか?

4

3 に答える 3

1

最初の例では、固定された一連の操作を実行する定型化された方法をクライアント コードに提供します。掛け算は簡単ですが、割り算をしたい場合は大変です。

2 番目の例では、実装の詳細をクライアントにプッシュします。これで、操作に依存しない計算フレームワーク全体が完成しました。これには、クライアント コードに関するより多くの知識が必要です。

したがって、実際に異なるのは抽象化のレベル、つまりクライアントにどれだけの知識を持たせたいかです。operator.mult他のロジック (乗算サーバーへの XML-RPC など) ではなく、使用するクライアントにとって重要な場合は、2 番目のオプションが適切と思われます。クライアントが 2 つの数値をどう処理するかをあなたよりもよく知っていて、フレームワーク (ある種のラッパー) のみを提供したい場合は、2 番目のオプションが適しています。人々に足し算や掛け算をさせたいだけなら、最初のオプションの方が良いでしょう。

于 2012-10-12T23:03:30.637 に答える
1

それは本当にクラスが何をするかに依存します。あなたの例では、クラスのロジックは非常に最小限であるため、メソッドのラッパーをクラスとして提供しただけであることは明らかです。そして、計算クラスを持つ方が理にかなっています。

実際の状況では、グループ化するさまざまな機能がどの程度まとまっているかを自問する必要があります。単一の責任は重要ですが、その不条理を受け入れる必要はありません

于 2012-10-13T19:59:03.220 に答える
0

それは、構築時に利用可能なオブジェクトに対して行う変換 (?) に関するすべての情報を持っているかどうかにかかっていると思います。そうしないと、より複雑なコンストラクターを呼び出すのに問題が発生します。

さらに、最初にクラスを設計するときは明らかではありませんが、特定のパスにコミットする前に、「基本」オブジェクトに対して何かを行うオプションを開いたままにしておくと、多くの場合役に立ちます。

一般に、必要最小限のパラメーターでコンストラクターを作成し、メソッドを介して他の機能を実装することが最善の解決策であることがわかりました。

ランダムな例の精神で、次のことを考慮してください。

パラメータ化されたコンストラクタ

class Image:
    # Some implementation

class Text:
    def __init__(self, image, whitelistChars):
        # This uses OCR to extract the text from an image then filters out 
        #   non-whitelisted characters
        #
        # image is an Image
        # whitelistChars is an interable containing characters that should 
        #   not be filtered out

im = Image('scan.tif')
t = Text(im, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ134567890');

基本コンストラクター

class Text:
    def __init__(self, image):
        # This uses OCR to extract the text from an image
        #
        # image is an Image


    def filter(self, whitelistChars):
        # This filters out non-whitelisted characters
        #
        # whitelistChars is an interable containing characters that should 
        #   not be filtered out

im = Image('scan.tif')
t = Text(im)
# <-- Are you interested in doing anything to the Text object t here?
t.filter('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ134567890')

「基本コンストラクター」の実装では、ホワイトリストに登録されていない文字を削除する前に、Textオブジェクトを使用するオプションがあります。t多分これは便利ですか?多分もっと重要なことに、これは将来役に立つでしょうか?

自信を持って「いいえ」と言えるのであれば、それは役に立たず、決して役に立たないでしょう。それなら、「パラメーター化されたコンストラクター」は問題ないと思います。filterどちらかといえば、余分な呼び出しの必要がなくなります。

tただし、コードを再利用したい場合は、変換する (この場合はテキストをフィルター処理する) 前に、を操作したり検査したりするオプションを開いたままにしておくと、多くの場合に役立ちます。

(私の $0.02)

于 2012-10-12T23:00:45.400 に答える