[英]Is it possible to dynamically add code to/extend a class?
我想为我的代码编写一种“插件/模块”系统,如果我可以在定义之后将其“添加”到类中,它会更容易。
例如,像这样:
class foo {
public function a() {
return 'b';
}
}
这是班级。 现在我想在定义后添加另一个函数/变量/ const。
我意识到这可能是不可能的,但我需要确认。
不,您无法在运行时向已定义的类添加方法。
但是您可以使用__call/__callStatic
魔术方法创建类似的功能。
Class Extendable {
private $handlers = array();
public function registerHandler($handler) {
$this->handlers[] = $handler;
}
public function __call($method, $arguments) {
foreach ($this->handlers as $handler) {
if (method_exists($handler, $method)) {
return call_user_func_array(
array($handler, $method),
$arguments
);
}
}
}
}
Class myclass extends Extendable {
public function foo() {
echo 'foo';
}
}
CLass myclass2 {
public function bar() {
echo 'bar';
}
}
$myclass = new myclass();
$myclass->registerHandler(new myclass2());
$myclass->foo(); // prints 'foo'
echo "\n";
$myclass->bar(); // prints 'bar'
echo "\n";
这个解决方案非常有限,但它可能适合您
要添加/更改类在运行时的行为方式,您应该使用装饰器和/或策略。 这是首选的OO方法,而不是采用任何魔术方法或猴子修补。
装饰器包装类的实例并提供与该实例相同的API。 任何调用都委托给包装实例,并在需要时修改结果。
class Decorator
{
// …
public function __construct($decoratedInstance)
{
$this->_decoratedInstace = $decoratedInstance;
}
public function someMethod()
{
// call original method
$result = $this->_decoratedInstance->someMethod();
// decorate and return
return $result * 10;
}
// …
}
对于策略,请参阅我的更完整的示例我可以将代码包含到PHP类中吗?
更多细节和示例代码可以在
我有几种方法供您尝试。 :)玩得开心编码。
class main_class {
private $_MODS = array(),...;
public ...;
public function __construct(...) {
...
global $MODS_ENABLED;
$this -> $_MODS = $MODS_ENABLED;
}
...
public function __get( $var ) {
foreach ( $this->_MODS as $mod )
if ( property_exists( $mod, $var ) )
return $mod -> $var;
}
public function __call( $method, $args ) {
foreach ( $this->_MODS as $mod )
if ( method_exists( $mod, $method ) )
return call_user_method_array( $method, $mod, $args );
}
}
class modMe {
private $_MODS = array();
public function __construct__() {
global $MODS_ENABLED;
$this -> $_MODS = $MODS_ENABLED;
}
public function __get( $var ) {
foreach ( $this->_MODS as $mod )
if ( property_exists( $mod, $var ) )
return $mod -> $var;
}
public function __call( $method, $args ) {
foreach ( $this->_MODS as $mod )
if ( method_exists( $mod, $method ) )
return call_user_method_array( $method, $mod, $args );
}
}
class mainClass extends modMe {
function __construct(...){
$this -> __construct__();
}
}
$MODS_ENABLED = array();
$MODS_ENABLED[] = new mod_mail();
$myObj = new main_class(...);
$myObj -> mail("me@me.me","you@you.you","subject","message/body","Extra:Headers;More:Headers");
# Hey look, my mail class was just added into my main_class for later use.
我目前正在使用第一种方法(我只有一个类,mods是例外)在我自己的CMS中,我从头开始(http://sitegen.com.au),它工作得很好,我需要的理由这是因为我已经生成了我的main_class,在我需要./mods-enabled / *创建函数和改变其他函数的工作方式的所有mod之后,我还会再次回到这里,为两个mod提供两个mod的解决方案在没有获胜的情况下更改功能,因为它首先运行。 我将我的插件拆分为两个,在每个站点上运行的mod,以及具有站点设置的插件,甚至可能都没有启用。
玩得开心。
如果它不够神奇,您可以使用动态对象。 常见的想法是: https : //github.com/ptrofimov/jslikeobject
你可以扩展课程
class foo {
public function a() {
return 'b';
}
}
class woo extends foo {
public function newStuff() {
$var = $this->a();
echo $var;
}
}
通过从woo类扩展foo,foo中的功能可用,同时您还可以在woo中创建新方法。 这是向类添加新功能的最简单方法。
您可以使用PHP的魔术功能来提供对编译时未定义的方法的操作。
这实际上是可能的。 例如:
<?php
class Test {
function set($set, $val) {
$this->$set = $val;
}
function get($get) {
return $this->$get;
}
}
$t = new Test();
$t->set('hello', 'world');
echo $t->get('hello');
exit;
?>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.