12

私はオープン/クローズドの原則を理解しようとしています(私の場合はPHPの場合ですが、それは実際には違いはありません)。

私が理解しているのは、クラスが変更のために開かれることは決してないということです。バグ修正のみ。クラスに新しいコードを追加したい場合は、新しいコードを作成して「古い」クラスを拡張する必要があります。それが私がそれに新しいコードを追加できる唯一の方法です。

ある意味で、私はこれの利点を見ることができます。基本的に、古いコードが常に機能するある種のバージョン管理システムを作成しますが、新しいクラスの使用もいつでも試みることができるためです。

しかし、これは実際にはどのように機能しますか?つまり、次のクラスがあるとします。

class MyObject
{
    public function doSomething()
    {
        echo 'Im doing something';
    }
}

だからどこかで私はおそらくこのクラスをインスタンス化しています:

$obj = new MyObject();

しかし、そのオブジェクトに別のメソッドを含めるのは良いことだと思います。だから私も何か他のことができます。OCPによると、クラスを変更することはできません。だから私は古いものに拡張する新しいものを作成する必要がありますか?

最初の問題。新しいクラスを呼び出すにはどうすればよいですか?それは実際には完全に新しいオブジェクトではないからです。好き。UserオブジェクトはUserオブジェクトです。別の方法が必要だからといって、いきなり完全に違う名前を付けることはできません。とにかく、私は新しいクラスを作成します:

class MyNewObject extends MyObject
{
    public function doSomethingElse()
    {
        echo 'Im doing something else now';
    }
}

これは、「MyObject」クラスをインスタンス化したコード行を変更して、「MyNewObject」クラスに置き換える必要があることも意味します。そして、それが複数の場所で行われている場合は、ソースコードを検索する必要があります...(ほとんどの場合、特定のクラスをインスタンス化するために「new」キーワードを使用するコントローラークラスのメソッドについて考えてみてください)。

同じことが基本的に継承にも当てはまります。古いクラスを継承する各クラスを見つけて、それを新しいクラスに置き換える必要があります。


つまり、基本的に私の質問は次のとおりです。

新しいメソッドを持つ新しいクラスにどのように名前を付けますか?いくつかの新しい機能を追加したからといって、クラスにまったく新しい名前を付けることができるわけではありません...

そして、「古い」クラスが複数の場所からインスタンス化(または継承)された場合はどうなりますか。それなら私はそれらすべての場所を見つけなければならないでしょう...利益はどこにありますか?

4

3 に答える 3

3

関数を追加することで、クラスの動作を変更することはないと私は主張します。

現在アプリでdoSomething()が呼び出されているすべての場合、クラスにdoSomethingElse()を追加するだけでは効果がありません。doSomething()を変更していないため、動作は以前と同じです。

doSomething()実装が特定の状況でそれをカットしていないと判断したら、クラスを拡張してdoSometing()をオーバーライドできます。繰り返しになりますが、オリジナルは以前と同じように動作しますが、新しいdoSomething()も使用できるようになりました。

これはオープン/クローズの厳密な定義に反することを理解していますが、これは現実の世界であり、それが私のコードでその原則を解釈した方法です。

于 2012-05-23T20:32:57.547 に答える
3

Open Closed Principleは、一種のバージョン管理システムとして使用することを目的としたものではありません。本当にクラスに変更を加える必要がある場合は、先に進んでそれらの変更を行ってください。新しいクラスを作成したり、古いクラスをインスタンス化したすべての場所を変更したりする必要はありません。

Open Closed Principleのポイントは、適切に設計されたシステムでは、新しい機能を追加するために既存の機能を変更する必要がないということです。システムに新しいクラスを追加する場合、そのクラスを参照する必要がある場所や、そのクラスに特別なケースがある場所を見つけるために、すべてのコードを検索する必要はありません。

クラスの設計が新しい機能を処理するのに十分な柔軟性を備えていない場合は、必ずクラスのコードを変更してください。ただし、コードを変更するときは、コードを変更せずに将来同様の変更を処理できるように、コードを柔軟にしてください。これは、変更を防ぐための手錠のセットではなく、設計ポリシーであることが意図されています。適切な設計上の決定により、時間の経過とともに、システムに新しい機能を追加するときに必要な既存のコードの変更はますます少なくなります。これは反復的なプロセスです。

于 2012-05-23T20:59:06.270 に答える
0

親クラスのコンストラクターを呼び出すMyNewObjectクラスにコンストラクターを作成する必要があります。

function __construct() {

    parent::__construct();

}

このようにして、新しいクラスをインスタンス化し、拡張されたクラスのすべての機能にアクセスできます。

その後、親クラスの関数をオーバーライドすることもできます(もちろんfinalとマークされていない限り)。

だからあなたはすることができます:

$newObj = new MyNewObject();

$newObj->doSomething();

$newObj->doSomethingElse();
于 2012-05-23T20:22:24.010 に答える