donxbje866688 2015-03-05 13:56
浏览 56
已采纳

PHP - 使用静态方法动态扩展父类

consider the following:

class A
{
    public static function bark()
    { echo 'woof'; }
}

class B extends A
{
    public static function speak()
    { echo 'hello'; }
}

A::speak();

// Fatal error: Call to undefined method A::speak()

How is one supposed to extend a class with methods that you need to be globally available within that class with methods that are not yet known, but are loaded at run-time, depending on the flow of your application?

Yes sure we can make traits and put use in the class like:

trait B
{
    public static function speak()
    { echo 'hello'; }
}

class A
{
    use B;
    public static function bark()
    { echo 'woof'; }
}

A::speak();

// hello
  • but then use B is not called dynamically, hence you will have to update class A with every new trait available - manually. This is absurd, why force developers to break their brain in trying to accomplish something so fundamentally simple?

Does anyone have an idea how this can be done in a clean way? I mean I have seen some impressive methods by using Singletons, namespaces, callbacks and the works, but in each case it requires a lot more code and repetitive programming than what is really needed. Either that or i'm missing the boat completely haha! Thanks in advance, your help will be appreciated and voted generously.

  • 写回答

1条回答 默认 最新

  • download2014711 2015-03-10 02:19
    关注

    I think with some creativity you could make use of the __call magic method. You could do something like this:

    class A
    {
        /**
         * @var array
         */
        protected $methods = [];
    
        public function __call($name, $arguments)
        {
            if (!empty($this->methods[$name]) && is_callable($this->methods[$name])) {
                return call_user_func_array($this->methods[$name], $arguments);
            }
        }
    
        public function addMethod($name, Closure $method)
        {
            $this->methods[$name] = $method;
        }
    }
    
    // get class instance (A have no methods except of addMethod)
    $instance = new A();
    
    // add methods on runtime
    $instance->addMethod('sum', function($num1, $num2) {
        return $num1 + $num2;
    });
    
    $instance->addMethod('sub', function($num1, $num2) {
        return $num1 - $num2;
    });
    
    // use methods exactly the same way as implemented fixed on class
    echo $instance->sum(2, 2);
    echo $instance->sub(3, 2);
    

    Of course you could use also __callStatic for static methods. And if you want to get it a bit more complex also could use the concept of Dependency Injection to add objects instead of methods. Then search the called method through the injected objects and call it when it's found. I hope this give you at least a good idea.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?