2017-09-20 8 views
1

名前の付け方はわかりませんが、ここにはあります。仮定することができます私はPHP OOPのクラスと関数

class A { 
    public function aa() { 
     $this->bb(); 
    } 
    public function bb() { 

    } 
} 

class B extends a { 

} 

class C { 
    __construct(B $service) { 
     $this->service = $service; 
    } 
    public function aa() { 

     $this->service->aa(); 
    } 
} 

次のコードで私の呼び出しは、だから、これは基本的に私が欲しいものであるA:aa()を実行します

$C = new C(new B()); 
$C->aa(); 

になりました。ご覧のとおり、A::aa()AA::bb()が呼び出されます。

私に必要なもの。 AA :: bb()が呼び出されたとき、クラスCで定義されたコードを実行したいが、Aクラスを変更することはできない。 BクラスまたはCクラスのみを変更できます。

私の考えはBクラスでリスナーを追加し、この

class B extends a { 
    public $listener; 
    bb() { 
     parent::bb(); 
     $this->listener(); 
    } 
} 

class C { 
    __construct(B $service) { 
     $this->service = $service; 
    } 
    public function aa() { 

     $this->service->listener = function() { } 
     $this->service->aa(); 
    } 
} 

のようにBB()関数を上書きすることでした。しかし、私はこのアイデアをたくさん好きではない、良いもののように見えていません。私の選択肢は何ですか?

私はAクラスを変更できません。私はCクラスのみを呼び出すことができます。

PHPバージョン5.3

+0

リスナーロジックをクラスBに直接保存することはできないため、あまりオプションはありません。 '$ this-> service-> listener = function(){}'をコンストラクタthoに移動します。なぜあなたはそれが気に入らないのですか? –

答えて

1

2つのオプションがあります。拡張または装飾する。

ちょっとすでに書かれたものだろう、しかし、私はリスナーの public可視性を使用していないだろう

まず1:

class Foo extends A { 
    private $listener; 
    public function setListener(callable $func) { 
     $this->listener = $func; 
    } 
    public function bb() { 
     call_user_func($this->listener); 
     return parent:bb(); 
    } 
} 

私はセッター・インジェクションを経由して、リスナーを通過した例では、しかし、あなたはまた、使用することができますオーバーロードされた__construct()メソッドの$listenedを渡します。あなたがクラスを拡張するとき、 "インタフェースの制限"は、コンストラクタのシグネチャには役立ちません。


他のアプローチは、デコレータを使用することです:

class Foo { 
    private $target; 
    public function __construct(A $target) { 
     $this->target = $target; 
    } 

    public function bb($callback) { 
     $callback(); 
     return $this->target->bb(); 
    } 

    public function __call($method, $arguments) { 
     return call_user_func_array( 
       array($this->target, $method), 
       $arguments 
      ); 
    } 
} 

第二のアプローチでは、インターフェイスを変更せます。

どのオプションを選択するかは、実際に実装する必要がある正確な機能によって異なります。デコレータは、オブジェクトの動作を大幅に変更する必要がある場合などに適しています。たとえば、アクセス制御を追加する場合などです。

+0

あなたの答えをありがとう。私が質問から省略したのは、実行されなければならないコードがCクラスの内部にある必要があるということです。あなたの例では、FooはBクラスかCクラスですか? – keepwalking

+0

これは 'B'クラスです。あなたはあいまいなクラス/メソッドは本当に助けにはなりません –

1

Aのコードが完了した後でCにコードを実行したいと思います。変更することはできません。

C::aaA::aaとなり、A::bbがコールされ、スタックは巻き戻されます。サービスコール終了後、C::aaで作業してみませんか?

class C { 
    public function aa() { 
     $this->service->aa(); 
     // whatever you want to do 
    } 
} 

A::aaが呼び出されますがA::bb前には、あなたが明快で十分であろう掲示その後、たとえば呼び出された後に他の一方で、あなたはコードを呼び出す必要があり、場合:

class B extends a { 
    public $listener; 
    public function bb() { 
     call_user_func($this->listener); 
     parent::bb(); 
    } 
} 

注意call_user_funcの使用。これは、PHP 5.3がメンバ変数に格納された無名関数を呼び出すために必要です。

関連する問題