23

私はWordPressをCMSとして使用しており、別のクラスから継承することなく、そのクラスの1つを拡張したいと考えています。つまり、そのクラスにさらにメソッドを「追加」したいだけです。

class A {

    function do_a() {
       echo 'a';
    }
}

それから:

function insert_this_function_into_class_A() {
    echo 'b';
}

(後者をAクラスに挿入する何らかの方法)

と:

A::insert_this_function_into_class_A();  # b

これは粘り強いPHPでも可能ですか?

4

5 に答える 5

28

クラスの Public API にのみアクセスする必要がある場合は、Decoratorを使用できます。

class SomeClassDecorator
{
    protected $_instance;

    public function myMethod() {
        return strtoupper( $this->_instance->someMethod() );
    }

    public function __construct(SomeClass $instance) {
        $this->_instance = $instance;
    }

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

    public function __get($key) {
        return $this->_instance->$key;
    }

    public function __set($key, $val) {
        return $this->_instance->$key = $val;
    }

    // can implement additional (magic) methods here ...
}

次に、SomeClass のインスタンスをラップします。

$decorator = new SomeClassDecorator(new SomeClass);

$decorator->foo = 'bar';       // sets $foo in SomeClass instance
echo $decorator->foo;          // returns 'bar'
echo $decorator->someMethod(); // forwards call to SomeClass instance
echo $decorator->myMethod();   // calls my custom methods in Decorator

protectedAPI にアクセスする必要がある場合は、継承を使用する必要があります。APIにアクセスする必要がある場合はprivate、クラス ファイルを変更する必要があります。継承アプローチは問題ありませんが、クラス ファイルを変更すると、更新時に問題が発生する可能性があります (作成したパッチが失われます)。しかし、どちらも runkit を使用するよりも実行可能です。

于 2010-06-10T07:20:47.263 に答える
10

スコープに対処する 2014 年の更新された方法。

public function __call($method, $arguments) {
    return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
}

例えば:

class stdObject {
    public function __call($method, $arguments) {
        return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
    }
}

$obj = new stdObject();
$obj->test = function() {
    echo "<pre>" . print_r($this, true) . "</pre>";
};
$obj->test();
于 2014-08-13T12:23:26.033 に答える
3

これにはrunkit拡張機能を使用できますが、代わりに通常の継承を検討する必要があります。

を参照してくださいrunkit_method_add

于 2010-06-10T05:49:36.060 に答える
3

問題のクラスが __call マジックを実装している場合、それは可能であり、非常に簡単です。これがどのように機能するかを知りたい場合は、Extending objects with new methods at runtimeを読むことをお勧めします。

于 2010-06-10T06:18:58.763 に答える
-3

いいえ、PHP で実行時にクラスを動的に変更することはできません。

これは、通常の継承を使用してクラスを拡張することで実現できます。

class Fancy extends NotSoFancy
{
    public function whatMakesItFancy() //can also be private/protected of course
    {
        //    
    }
}

または、Wordpress のソース ファイルを編集することもできます。

私は継承の方法を好むでしょう。長い目で見れば、はるかに扱いやすいです。

于 2010-06-10T06:24:33.920 に答える