代码之家  ›  专栏  ›  技术社区  ›  Gal

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

  •  14
  • Gal  · 技术社区  · 16 年前

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

    class A {
    
        function do_a() {
           echo 'a';
        }
    }
    

    然后:

    function insert_this_function_into_class_A() {
        echo 'b';
    }
    

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

    以及:

    A::insert_this_function_into_class_A();  # b
    

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

    5 回复  |  直到 16 年前
        1
  •  27
  •   Gordon Haim Evgi    16 年前

    如果您只需要访问类的公共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 ...
    }
    

    $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更可行。

        2
  •  9
  •   Chris    12 年前

    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();
    
        3
  •  3
  •   wimvds    16 年前

    如果所讨论的类实现了调用魔法,那么这是可能的,而且非常简单。如果你想知道这是怎么回事,我建议你读一读 Extending objects with new methods at runtime

        4
  •  3
  •   Pang Ajmal PraveeN    9 年前
        5
  •  -3
  •   selfawaresoup    16 年前

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

    class Fancy extends NotSoFancy
    {
        public function whatMakesItFancy() //can also be private/protected of course
        {
            //    
        }
    }
    

    或者你可以编辑Wordpress源文件。

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

    推荐文章