如何在PHP中将方法添加到现有类中?

2022-08-30 17:44:48

我将WordPress用作CMS,并且我想扩展其中一个类,而不必从另一个类继承;即,我只想向该类“添加”更多方法:

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中甚至可能吗?


答案 1

如果只需要访问类的公共 API,则可以使用装饰器

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

如果需要访问 API,则必须使用继承。如果需要访问 API,则必须修改类文件。虽然继承方法很好,但修改类文件可能会在更新时遇到麻烦(您将丢失所做的任何补丁)。但两者都比使用runkit更可行。protectedprivate


答案 2

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();

推荐