Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在PHP中向现有类添加方法?_Php_Class_Extend_Inheritance - Fatal编程技术网

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

如何在PHP中向现有类添加方法?,php,class,extend,inheritance,Php,Class,Extend,Inheritance,我使用WordPress作为CMS,我想扩展它的一个类,而不必从另一个类继承;i、 e.我只想向该类“添加”更多方法: class A { function do_a() { echo 'a'; } } 然后: (将后者插入类的某种方式) 以及: 这在顽强的PHP中也是可能的吗? 你可以使用它,但是你应该真正地考虑正则继承。 请参阅。如果所讨论的类实现了调用魔法,那么它是可能的,而且非常简单。如果您想知道它是如何工作的,我建议您阅读。不,您不能在PHP运行时动态

我使用WordPress作为CMS,我想扩展它的一个类,而不必从另一个类继承;i、 e.我只想向该类“添加”更多方法:

class A {

    function do_a() {
       echo 'a';
    }
}
然后:

(将后者插入类的某种方式)

以及:

这在顽强的PHP中也是可能的吗?

你可以使用它,但是你应该真正地考虑正则继承。
请参阅。

如果所讨论的类实现了调用魔法,那么它是可能的,而且非常简单。如果您想知道它是如何工作的,我建议您阅读。

不,您不能在PHP运行时动态更改类

您可以通过使用常规继承扩展类来实现这一点:

class Fancy extends NotSoFancy
{
    public function whatMakesItFancy() //can also be private/protected of course
    {
        //    
    }
}
或者您可以编辑Wordpress源文件


我更喜欢继承的方式。从长远来看,它更容易处理。

如果您只需要访问类的公共API,可以使用:

然后包装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,则必须使用继承。如果需要访问
private
API,则必须修改类文件。虽然继承方法很好,但修改类文件可能会在更新时给您带来麻烦(您将丢失任何已制作的修补程序)。但两者都比使用runkit更可行。

这是2014年应对范围的更新方式

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

类stdObject{
公共函数调用($method,$arguments){
返回call_user_func_数组(Closure::bind($this->$method,$this,get_called_class()),$arguments);
}
}
$obj=新stdObject();
$obj->test=函数(){
echo“.print\u r($this,true)。”;
};
$obj->test();

编辑类源代码是一种选择吗?标题有误导性;“扩展”指的是继承。我把它改了,以便更好地反映你的问题。@谢谢。我觉得这有点模棱两可。。。。而runkit只不过是一个玩具。@johannes它有时在调试时很有用。但这就是我提出建议的原因,然而,这并不妨碍我回答这个问题。注意手册页面上的红色大“实验性”警告?不推荐用于任何生产用途…@Techpriester您的观点是什么?OP应该考虑使用另一种策略吗?我明白了,这个建议已经包含在回复中了。然而,这是一个有效的解决办法。尽管有人提出建议,我还是试图回答这个问题。此外,你假设得太多了。也许OP没有把它用于制作(他没有说他是)。也许他正以runkit为起点,编写自己的稳定扩展来实现同样的功能。无论什么我无意预测所有可能的情况;我试着将问题局限于实际问题,并将事后的猜测作为一种附带的游戏。是的,但我只是想明确指出,您不应该在其上构建一个关键的应用程序,该应用程序可以在ProductionProblem中运行,但它添加了大量讨厌的代码,以后可能很难维护。尤其是“$func=$foo->baz;$func();”上可能写满了失败的信息:我知道它很难维护,调试起来会很困难,我当然不建议使用它,但这是可能的:p.Great!。这不仅适用于向类添加新方法,还适用于在“extends”不是选项时覆盖它们。嗯……这实际上不会向原始对象添加方法,例如(与任何类型的继承或php
extends
),但这是一个基本上起作用的设计变通方法。这对于任何类名都非常有效。在$obj->test中,您还可以执行$this->someClassMethod()和$this->privateVarName。您还可以在成员函数中创建函数,这些函数可以访问类方法和变量。
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 ...
}
$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
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();