5

継承チェーンには2つの抽象クラスがあり、最終的には汎用ライブラリになります。

abstract class Foo {
    public function baz() {
        echo 'Foo::baz()';
    }

    // other methods here
}

abstract class Bar extends Foo {
    public function baz() {
        echo 'Bar::baz()';
    }
}

これらの2つのクラスは開発者によって拡張されることを意図しており、私の問題は、baz()メソッドのどちらの実装もオーバーライドできないようにすることです(厳密なRFC準拠のコードが含まれているため)。作るBar::baz() finalのは問題ありません。ただし、を作成した場合Foo::baz() final、それBar自体も明らかにオーバーライドできません。

PHP 5.4traitは実用的な解決策を提供する可能性がありますが、これ以上PHP<5.4のサポートをやめることはできません。私の最後の手段は、そのままにして、ドキュメントを使用して開発者にこのメソッドをオーバーライドしないように警告することですが、可能であれば、より具体的なものを見つけたいと思います。

コードをDRYに保ちながら(たとえば、継承を削除せず、すべてのコードを複製しないで)、両方のメソッドをオーバーライドしないように強制するために使用できる他の設計はありますか?

4

3 に答える 3

2

私はこれを行う方法を手に入れたと思います。本当にすっきりとしたデザインというよりはコツですが、要点はわかったと思います。

abstract class Foo {
private $bazBehaviour;
    public function __construct($bazBehaviour){
        $this->bazBehaviour=!empty($bazBehaviour)?$bazBehaviour:"defaultBazBehaviour";
    }
   final public function baz() {
       $this->bazBehaviour();
   }
   final protected function defaultBazBehaviour(){
        echo "Foo::Baz()";
    }
   // other methods here
}

abstract class Bar extends Foo {
    public function __construct(){
       parent::__construct("bazBehaviour");
    }
    final protected function bazBehaviour() {
        echo 'Bar::baz()';
     } 
}
class toto extends Bar{
     public function __construct(){
       parent::__construct();
    }
}
$d = new toto();
$d->baz();

PHP 5.3.13では、次を送信します:Bar :: Baz()

于 2012-08-17T06:52:50.547 に答える
1

これは、「継承よりもコンポジションを優先する」という考え方が当てはまる状況のようです。少し繰り返しますが、実装の繰り返しを必要とせず、必要な機能を提供します。

interface Bazr {
    public function baz();

    public function myOtherMethod1();
    public function myOtherMethod2();
}

public class Foo implements Bazr {
  public final function baz() {} 
  public function myOtherMethod1() {/* default implementation of some method */}
  public function myOtherMethod2() {/* yeah */}
}

public class Bar implements Bazr {
  private parentBazr = null;
  public function __construct() {
    $this->parentBazr = new Foo();
  }

  public final function baz() {}
  public function myOtherMethod1() {
    $this->parentBazr->myOtherMethod1();
  }
  public function myOtherMethod2() {
    $this->parentBazr->myOtherMethod1();
  }
}

FooとBarの両方を拡張でき、BarはFooの機能を「構成」し、bazはFooとBarの両方で最終的なものになります。インターフェイスを含めるか省略するかはわかりません...PHPには型変数がないため、2つの実装クラスとのコントラクトを適用する以外に必要ない可能性があります。インターフェイスを定義することの欠点は、他の人がインターフェイスを実装できることです(ただし、トレイトの場合も同様です)。

java / php構文を混在させた場合、申し訳ありませんが、いくつかの「$」を省略したと思います。

于 2012-08-17T08:12:13.200 に答える
0

申し訳ありませんが、あなたの要件は矛盾しています:

my problem is that I'd like to make it so that neither implementation of 
the baz() method can be overridden

ただし、.. soでオーバーライドしているため、ここでの設計/要件にはいくつかの基本的な問題があります。Foo:baz()Bar

于 2012-08-16T18:06:30.023 に答える