5

私は最近、特定のケースで実際にやりたいこと (super を呼び出す) がアンチパターンであることに気付きました。( http://en.wikipedia.org/wiki/Call_super )

だから私の質問は:

次のことを行う方法 (ほとんどの人が必要とする基本的なことで、オブジェクトに詳細を追加します)。オブジェクト var に保持されている配列に新しい要素を追加するだけです。

   <?php
   class A {
       // bla bla bla
       public function __construct() {
            $this->_data['newDetail'] = "Ipiicaei";
       }
   }


   class B extends A {
       // bla bla bla
       // Override constructor, I need to add one more detail for this class
       public function __construct() {
            parent::__construct();
            $this->_data['newDetailSubcls'] = "Something";
       }
   }

さて...最初の要素を追加するために親クラスのコンストラクターを呼び出さない場合、2 つの可能性があります。

  1. 各サブクラスで、親が通常実行しているコードの一部を追加し、親から削除します。したがって、999 クラスで拡張すると、999* 行が親に複製されます。私には悪いように聞こえます。

  2. 子に実装されている親からメソッドを呼び出します(テンプレートメソッドパターン、推奨事項)。したがって、それを追加するクラスが 1 つだけ必要で、残りの 998 個が親とまったく同じように動作する必要がある場合は、それぞれに空の関数を追加します。これも私には悪いように聞こえます。

私の例は単純ですが (これが例のあり方です)、親クラスやサブクラスが複雑なことを行う可能性があることに注意してください。

call super が状況によっては良くない理由がわかります。しかし、これは私には問題ないようです。

では、どのようにアプローチしますか?call super がアンチパターンであることを無視して、私と同じようにしますか (または、私の方法が悪いことが判明した場合は、以前はそうしていましたか)? または...どのように?

4

1 に答える 1

4

コンストラクターの使用は、このアンチパターンがどのように発生するかの一種の悪い例です。PHP では、継承をサポートするほとんどの言語と同様に、

子がコンストラクターを定義していない場合は、通常のクラス メソッドと同じように親クラスから継承できます ( PHP マニュアルから)。

定義しようとしている他の 998 クラスのいずれかに意図的にコンストラクターを含めない場合、基本コンストラクターが呼び出されるため、この機能を回避するために各派生クラスにコンストラクターを追加することがほぼ必須になります。これが、保護されたフィールド/プロパティの状態を変更する可能性のあるロジックをコンストラクターに追加したり、派生クラスでオーバーライドされる可能性のある仮想メソッドを呼び出したりすることをお勧めしない理由です。

ただし、アンチパターンは実際には次のことを表現しています。

アンチパターンである親を呼び出す必要があることに注意してください(ウィキペディアから)

したがって、派生クラスによって必要とされない限り、メソッドの基本クラス バージョンを呼び出すことは問題ありません。基本メソッドが呼び出されない場合でも、派生クラスは正しく動作する必要があります。これにより、派生クラスが仮想メソッドをオーバーライドするが、いくつかの特別な要件を実装しない (おそらく基本クラスのドキュメントがないため) というシナリオが回避されます。システムがクラッシュしたり、予想外の動作をしたりします。これは、リスコフの置換原則の典型的な違反です。

特定の例では、このアンチパターンは適用されません。コンストラクターを拡張しています。コンストラクターは、定義により、クラスをインスタンス化して有用な状態にするときに呼び出す必要があります。そしてほとんどの場合、それはあなたが望むものです。

于 2013-06-17T20:02:50.927 に答える