2

オブジェクトのコードに実際に触れることなく、オブジェクト メソッドの結果を変更するコードを実行する方法を見つけようとしていました。私が思いついた1つの方法は、デコレータを使用することです:

class Decorator {
    private $object;

    public function __construct($object) {
        if (!is_object($object)) {
            throw new Exception("Not an object");
        }
        $this->object = $object;
    }

    protected function doSomething(&$val) {
        $val .= "!!";
    }

    public function __call($name, $arguments) {
        $retVal = call_user_func_array(array($this->object, $name), $arguments);
        $this->doSomething($retVal);
        return $retVal;
    }
}

class Test extends BaseTest {
    public function run() {
        return "Test->run()";
    }
}

$o = new Decorator(new Test());
$o->run();

そうすれば適切に動作しますが、現在は使用できないという欠点があります。すべての行をnew Test()で置き換える必要がnew Decorator(new Test())あり、これはまさに私が避けたいことです。たぶん、基本クラスで何かできるでしょうか?

4

3 に答える 3

3

PHP で単純にオーバーロードすることはありません。だから、あなたが望むことはできません。しかし、あなたが今問題を抱えているという事実は、あなたのデザインに欠陥があることを示しています. または、それがあなたのコード設計ではない場合は、作業しなければならないコードです (私はあなたの痛みを感じます)。

やりたいことができないのは、コードが密結合しているからです。つまり、必要なクラス/メソッドにキーワードを注入 (依存性注入new)する代わりに、クラスでキーワードを使用します。

クラスを簡単に交換できないことに加えて、緊密な結合のためにユニットを簡単にテストするのに時間を費やすことになります。

アップデート

完全を期すために(将来の読者のために):特定のクラスが名前空間化されていて、名前空間を変更することが許可されていた場合、名前空間を変更することを考えることができました。ただし、これはオートローダーなどを台無しにする可能性があるため、実際には良い方法ではありません。この例はPSR-0です。しかし、どちらの方法でもこれを行うことができないことを考えると、あなたが望むことが可能であるとは思えません。PSこの「ソリューション」を実際に使用しないでください。

更新2

ある時点でオーバーロード拡張機能があったようですが (かなりのことです)、それについて私が見つけた唯一のことは、いくつかのバグレポートです。いずれにせよ、今でも機能しているとは考えないでください。;-) PHP には実際のオーバーロードはありません。

何かが見つかりました (クラスのオーバーロードを可能にする、機能しなくなったデッド プロジェクト): http://pecl.php.net/package/runkit

おそらく別のプロジェクト(もちろん死んでいます):http://pecl.php.net/package/apd

于 2013-01-04T09:22:44.020 に答える
0

デコレータパターンに関するウィキペディアの記事から:

  1. 元の「Decorator」クラスを「Component」クラスにサブクラス化します

ですから、あなたはクラスをプライベートに装飾し、すでに装飾されたクラスだけを公開することになっていると思います。

于 2013-01-04T09:29:40.047 に答える
0

私は PHP プログラマーではありませんが、あなたが求めているのはAOPだと思います。この回答にリストされているなど、いくつかのフレームワークを試すことができます。

于 2013-01-04T09:25:18.330 に答える