2

私が見る非常に一般的なパターン(この質問の時点でZend Frameworkを扱っていたという理由だけで、Zend Frameworkを選択しています)は、次のようなものです。

class My_Form extends Zend_Form {
     public function init() {
          $this->addElement();
     }
}

Zend_Formは抽象クラスではありませんが、それ自体で完全に使用できます。これは、フォームを素敵なクラスに「カプセル化」する場所として「推奨」されているようです。

これはリスコフの置換原則に違反しますか?Zend_Formの各サブクラスは、基本クラスとは大きく異なる動作をします。これにはコンポジションを使用する方が良いでしょうか、それとも私はこの原則を完全に誤解していますか?

4

2 に答える 2

0

リスコフの置換原則は、プログラムモジュールがBaseクラスを使用している場合、プログラムモジュールの機能に影響を与えることなく、Baseクラスへの参照をDerivedクラスに置き換えることができると述べています。

では、MyFormとZendFormの違いは何ですか?プログラムの機能は変わりますか?

また、これらの2つの箇条書きを確認してください(ウィキペディアの記事から):

  • サブクラスで前提条件を強化することはできません。
  • サブクラスで事後条件を弱めることはできません。

おそらく、MyFormはZendFormとそれほど劇的な違いはなく、継承を安全に使用できることがわかるでしょう。

于 2009-05-21T20:38:05.960 に答える
0

Zend_Formは継承用に設計されています。Zend_Formを使用している間は、誰もがそれを覚えておく必要があります。実際には、Zend_Formは必要ありませんが、そのサブクラスである可能性があります。したがって、プログラムがZend_Formに依存して、そのサブクラスが動作できるようにではなく、正確に動作する場合、そのプログラムは間違っています。リスコフの原則が述べているように、それは「基本クラスを使用する」のではなく、それを悪用しています。

Zend_Formは主にZendフレームワークで使用されており、正しく使用されていると確信しています。

継承用に設計され、何らかのフレームワークに基づいてアプリケーションのビルドブロックとして使用されるこのようなクラスの場合、「動作」の定義はより抽象的である必要があります。クラス自体が抽象的でなくても、サブクラスに詳細を残します。Zend_Formの動作は、「いくつかのhtmlをレンダリングし、いくつかの検証ルールを使用する」ことだと思います。この意味で、Zend_Formのすべてのサブクラスは同じように動作します。Zend_Formが非抽象的であることは、使いやすくするデフォルトの動作を定義するだけです。

また、もう少しアカデミックにするために、それから2つのクラスを作成することができます。1つは抽象的である必要があります-すべてのフォームの基本クラス。もう1つは空のフォーム用で、正確に動作し、Zend_Formは現在動作し、それ自体で使用できます。だからそれは次のようなものになります

// sorry, I don't like PHP so here goes java 
public abstract class ZendForm{/*implementation here and NO abstract methods*/} 
public final class DefaultZendForm extends ZendForm{/*nothing here*/}

これにより、リスコフの原則に関する混乱は解消されますが、プログラムに実際の価値が追加されることはおそらくないでしょう。

サブクラスはスーパークラスとは何らかの方法で異なる必要があります。そうでない場合、サブクラスを作成しても意味がありません。そして、いつでもこの違いを悪用して、スーパークラスで機能し、サブクラスで失敗するプログラムを作成できます。しかし、それは合理的ではありません。正確にデフォルトの(空の)フォームをレンダリングすることは、Zend_Formの契約の一部ではありません。クラスコントラクトの一部である動作のみがLSPの対象となります。

于 2009-06-09T22:03:02.477 に答える