2012-01-12 3 views
2

多くのオブジェクトがすべて、create()edit()retrieve()およびdelete()のようなメソッドを定義する抽象クラスに拡張されているアプリケーションがあります。各子クラスはこれらの関数で同じロジックを使用するので、抽象クラスはそのデフォルトの動作を定義し、補完が必要な場合もあります。Prevent/Restrict Method継承

今、子クラスの一部を変更できないようにする必要があります。つまり、edit()またはdelete()のメソッドを持つべきではありません。これは、不変クラスが実装できるような、immutableのような名前のインターフェイスの仕事のようなものです。問題は、メソッドがメソッドの存在を強制するだけで、メソッドの呼び出しを停止しないということです。だから、これは明らかにうまくいかないでしょう。

2つの親クラスを作成すると、1つは可変オブジェクト用、もう1つは不変オブジェクト用ですが、おそらくメンテナンス行の問題を尋ねています。私は不変のオブジェクトを何もしなかった空のメソッドで問題のメソッドをオーバーライドさせることができましたが、それはまた乱雑に思えますし、その時点で適切なOOPをやっていないようです。

大きなセットのクラスがすべて一連のメソッドを継承できるようにするには、どのような方法を継承しない方が良いでしょうか? (問題のアプリケーションはPHPで書かれていますが、どの言語の一般的なOOPテクニックも役立ちます)。

答えて

2

基本クラスの子として不変ベースのクラスを作成します。 immutable-baseは、何もしないか、エラーを投げるedit()とdelete()のオーバーライドをfinalオーバーライドして実装する必要があります。

決勝、すべての不変の子はこの戦略に容易

  • ボーナスを編集または削除することはできないことが保証されているように、オブジェクトがinstanceofは不変ベースのためにテストすることによって不変であるかどうかを確認

  • 簡単にそれが

を渡ったもの・修正により再び不変のオブジェクトを変更し、
+0

だから私が正しく理解すれば、階層は次のようになります:Base-> Immutable_Base-> Immutable_ChildrenとBase-> Mutable_Children?その時点で、Mutable_BildクラスをBaseクラスとMutable_Childrenクラスの間に配置する方が良いでしょうか? –

+1

IMHO Mutable_Baseは、Mutableが基本ケースであるため不要です。しかしそれはあなたとあなたの美意識に左右されます。クラスツリーの対称性を強く好む人もいます。 –

0

私はこれに対するJavaのアプローチが好きです。例外をスローします。 UnsupportedOperationExceptionを作成し、特定のメソッドを使用しない実装では、この実装でこの機能を使用できないことをユーザーに知らせるために、特定のメソッドをスローします。

+0

例外をスローするには、まだ 'edit()'と 'delete()'メソッドをオーバーライドする必要があります。そして、私は非常にDRYのように見えないすべての不変のクラスでそれをしなければならないでしょう。例外をスローすることは、私が言う必要がある空のメソッドでオーバーライドするよりも便利です。 –

+1

このメソッドをオーバーライドする必要がありますが、1行の例外スローが実際にDRYの原則に違反しているかどうかはわかりません。オーバーライド回数を減らしたいのであれば、適切な例外をスローする抽象クラスを作成するだけで、不変なオブジェクトは単純にそれを継承します。 – cspray

0

私は可能な解決策として捨てたいと思っていたもう一つの考え。クラスは、次のようなインタフェースを実現することができます。

Interface Immutable { 
    const immutable = true; 
} 

をして、基本抽象クラスは、これはまた、クラスの他の分類にも延長する

if (!$this->immutable) { 
    //do_stuff 
} 

delete()edit()メソッドを書くことができ、 NonDeletableやNonEditableのように、より細かい動作を可能にします。

2

実際には、空のメソッドやエラーをスローするクラスを作成するのは悪いです。そのようなメソッドは混乱し、スペースを取って何もしません。

より良いアプローチは、不変クラスを基本クラスにして、変更可能クラスを修正するメソッドを追加してそれを拡張することです。この方法では、各クラスには実際にそこに属するメソッドしかありません。ここで

0

は、あなたの方法は、最終的な作りとし、それを起動し、スーパーショート回避策です:

if(self::class!=static::class) return;#or throw an error 

それは継承自体を防ぐことはできませんが、方法は(エラーの有無にかかわらず、子供のクラスでは動作しません - までです君は)。

0

PHP 5.4以降では、Traitsを使用できます。

trait EditTrait { 
    public function edit() {/*...*/} 
} 

trait DeleteTrait { 
    public function delete() {/*...*/} 
} 

あなたが、その後になります。そして、あなたは形質のカップルを定義することができ

class EntityManager { 
    public function create() {/*...*/} 
    public function retrieve() {/*...*/} 
} 

を:

はたとえば、あなただけのすべての子クラスが持つメソッドが含まれる基本クラスを作ることができます次のような不変の子クラスを作成します。

class LogManager extends EntityManager { 
    ... 
} 

そして、

  • コードの重複をなくし:

    class ContactManager extends EntityManager { 
        use EditTrait; 
        use DeleteTrait; 
    
        ... 
    } 
    

    済みの特徴は、以下のような、ここで他のソリューションの一部を超えるいくつかの利点がありますされています。

  • シングルベースクラス。
  • 動作しない、または意味を成さないメソッドは、それらをサポートしないクラスには表示されません(特に、ドキュメントやapisでは重要です)。