2012-05-23 14 views
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'キーワードを使用します)。

同じことが基本的に継承に適用されます。私は古いクラスを継承する各クラスを見つけなければならず、新しいクラスと置き換える必要があります。


だから基本的に私の質問は以下のとおりです。

どのように新しいメソッドを持つ新しいクラスに名前を付けるのですか?私はいくつかの新しい機能を追加するだけbecasue、「古い」classsが複数の場所からインスタンス(または継承)されている場合、私は...クラスに

そして、何を全く新しい名前を付けることができ意味するものではありません。そして、私はそれらの場所のすべてを見つけなければならないでしょう...利益はどこですか?あなたは新しいクラスをインスタンス化して、まだ拡張1のすべての機能にアクセスすることができます

function __construct() { 

    parent::__construct(); 

} 

この方法:

+1

'$ x = new MyObj_version_3.14159265()'? mmmmm。パイ。 –

+1

[Open/closed principle](http://en.wikipedia.org/wiki/Open/closed_principle)を解釈するには2通りの方法があることに注意してください。あなたは主に古いもの(Meyers)を考えているようですが、そのユースケースは最近、代表団によって通常扱われます。 –

+0

もっと現実的な例でこの質問に答える方が簡単でしょう。名前の付け方などはもっと明白だと思います。 – Fuhrmanator

答えて

3

オープンクローズドプリンシプルは、バージョンコントロールシステムの一種として使用するためのものではありません。あなたが本当にクラスを変更する必要がある場合は、その変更を行ってください。新しいクラスを作成して、古いクラスをインスタンス化したすべての場所を変更する必要はありません。

オープン・クローズド・プリンシパルのポイントは、うまく設計されたシステムでは、新しい機能を追加するために既存の機能を変更する必要がないということです。新しいクラスをシステムに追加する場合、そのクラスを参照する必要のある場所を探したり、特別なケースを持つ必要がある場所を見つけるために、すべてのコードを検索する必要はありません。

クラスのデザインが新しい機能を処理するのに十分な柔軟性を持っていない場合は、必ずクラスのコードを変更してください。しかし、コードを変更するときは、コードを変更せずに将来同様の変更を処理できるように、コードを柔軟にしてください。それはあなたが変更をしないようにする手錠のセットではなく、デザインポリシーであることを意図しています。優れた設計上の決定を下せば、システムに新しい機能を追加するときに、既存のコードの変更が少なくて済みます。それは反復的なプロセスです。

0

あなたは、親クラスのコンストラクタを呼び出し、あなたのMyNewObjectクラスのコンストラクタを作成する必要があります。

あなたは、その後も(それはもちろん、最終的にマークされていない限り)親クラスのすべての機能を無効にすることができます。

だから、あなたができる:

$newObj = new MyNewObject(); 

$newObj->doSomething(); 

$newObj->doSomethingElse(); 
+0

はい、私は親コンストラクタを呼び出さなければならないことを知っています。さもなければ、継承はそれほど役に立たないでしょう:) ---しかし、あなたの例では、 "MyObject"ではなく "MyNewObject"のインスタンスも作成しています。あなたは新しい機能を使いたいからです。しかし、これはまた、一度「MyObject」をインスタンス化したコード内のすべての行を変更する必要があることを意味します。これを "MyNewObject"に変更する必要があります。これは、古いインスタンス化を新しいものに変更するためにコード全体を検索しなければならない場合、私にはかなりのOOを感じることはありません。 – w00

+0

ええ、私はあなたのポイントを参照してください。あなたがOOPを少し新しくしたと仮定して私を許してください。 – Steven1978

3

私は機能を追加することによって、あなたはクラスの振る舞いを変更していないことを主張するだろう。

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

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

これはopen/closedの厳密な定義に反していることに気付きましたが、これは現実の世界であり、私のコードでその原則をどのように解釈したかです。

+0

私は同意する、新しいメソッドを追加することはそれが壊れていません。私が与えた例ではありません。しかし、メソッドに変更を加えるコードをいくつか実行する必要がある場合は、新しいクラスを作成しなければならないと思います。しかし、私の2つの質問はまだ残っています。どのように新しいクラスの名前を付けますか?そして、それは私が古いクラスをインスタンス化した場所を見つけるために私のコード全体を検索しなければならないので、新しいクラスでそれを変更することができますか?最後の1つは、実際に私を悩ますものです...私はこの原則では利益を見ません。 – w00

+1

あなたはこれとは逆のことを考えるべきです:あなたのサブクラスに明白な名前がない場合は、おそらくそれを作ってはいけません!サブクラスは壊れたクラスを修正するために使用されるべきではありません。壊れたクラスは修正する必要があり、壊れた動作に依存する呼び出しコードも修正する必要があります。 (つまり、壊れたクラスを修正するためにサブクラス化する必要がある場合もありますが、通常は親クラスまたはその呼び出しコードを制御できないためです) –

+1

ところで、サブクラスを作成する2つの理由:より抽象的な基本クラス(多相継承)、または余分な機能を持ちながら[Liskov Substitution Principle](http://en.wikipedia.org/wiki/Liskov_substitution_principle)に従うサブタイプを作成することができます。どちらの場合も、新しい名前が明白でなければなりません。 –

関連する問題