你要求的基础PHP不可能。有几种方法可以做类似的事情。
您可以使用高度实验性的runkit扩展名。 runkit_class_emancipate和runkit_class_adopt函数应该可以工作。但是,它们在整个班级上运行,而不是班级的实例。这可能会限制您的应用程序的用处。
如果您试图模拟其他语言(如Ruby和Perl)的可扩展类功能,则可能更适合使用runkit_method_add和相关功能。然而,它仍然在整个课程上运行。
通常接受的“PHP方式”来做这种事是通过__call。事实上,在5.3 anonymous functions,你可以这样做......
class Bar {
public function say($thing) {
echo "Bar::say says: $thing\n";
}
}
class Foo extends Bar {
private $extensions = array();
public function addExtension($func_name, $func) {
$this->extensions[ $func_name ] = $func;
}
public function __call($func_name, $arguments) {
array_unshift($arguments, $this);
if(array_key_exists($func_name, $this->extensions))
call_user_func_array($this->extensions[ $func_name ], $arguments);
}
}
$f = new Foo();
$anon = function($obj, $string){ $obj->say($string); };
$f->addExtension('example', $anon);
$f->example("Hello, world!");
你会在__call注意,并在创建的第一个参数成为实例的匿名函数。这是因为PHP 5.3的匿名函数的实现不能引用$this
。这也意味着他们不能引用该类的受保护或私人成员。这可以通过克隆实例并使用Reflection来公开受保护和私有成员来纠正。有关示例实现,请参见this comment on the anonymous function manual page。
由于PHP的限制,您不能直接将匿名函数分配给属性并调用它。这个例子将不能工作:
class WillNotWork {
public $fatal_error;
}
$broken = new WillNotWork();
$anon = function($arg) { echo "I'm about to create a {$arg} error!"; };
$broken->fatal_error = $anon;
$broken->fatal_error("fatal");
// Fatal error: Call to undefined method WillNotWork::fatal_error()
不,这是不可能的。但是,根据您尝试解决的具体问题,可能有其他解决方法。 – igorw 2010-07-15 10:01:51