我正在使用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中是否可能?
答案 0 :(得分:20)
如果您只需要访问该类的公共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
如果您需要访问protected
API,则必须使用继承。如果您需要访问private
API,则必须修改类文件。虽然继承方法很好,但修改类文件可能会让您在更新时遇到麻烦(您将丢失所有补丁)。但两者都比使用runkit更可行。
答案 1 :(得分:5)
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();
答案 2 :(得分:3)
您可以使用the runkit extension,但您应该考虑定期继承。
答案 3 :(得分:2)
如果有问题的类实现__call魔术,那么它是可能的,而且非常简单。如果你想知道它是如何工作的,我建议你阅读Extending objects with new methods at runtime。
答案 4 :(得分:-2)
不能在PHP中运行时动态更改类。
您可以通过使用常规继承扩展类来实现此目的:
class Fancy extends NotSoFancy
{
public function whatMakesItFancy() //can also be private/protected of course
{
//
}
}
或者您可以编辑Wordpress源文件。
我更喜欢继承方式。从长远来看,处理起来容易得多。