PHP:在子类中包装类的所有函数

时间:2012-03-01 22:29:23

标签: php inheritance override metaprogramming aop

使用PHP库类,我希望将其所有公共函数包装在子类中......以下内容:

class BaseClass
{
   function do_something()
   {
        some;
        stuff;
   }

   function do_something_else()
   {
        other;
        stuff;
   }

   /*
    * 20-or-so other functions here!
    */
}

class SubClass extends BaseClass
{
   function magicalOverrideEveryone()
   {
        stuff-to-do-before;        // i.e. Display header
        call_original_function();  // i.e. Display otherwise-undecorated content
        stuff-to-do-after;         // i.e. Display footer
   }
}

将其简化,我不希望不必使用相同的包装代码覆盖每个超类方法,如果有一种[有点优雅/干净]的方式在一个地方完成所有这些。

这可能吗?我怀疑我是在这里进行元编程的,并且甚至不知道PHP是否提供了这样的野兽,但我想问我......

4 个答案:

答案 0 :(得分:20)

您可以使用__call magic method和一个不直接从基类继承的通用“代理”类轻松完成此操作。

这是一个代理类的(近)完整实现,它包装你传递它的任何对象。它将围绕每个方法调用调用一些“之前”和“之后”代码。

class MyProxy {
  function __construct($object) {
    $this->object = $object;
  }

  function __call($method, $args) {
    // Run before code here

    // Invoke original method on our proxied object
    call_user_func_array(array($this->object, $method), $args);

    // Run after code here
  }
}


$base = new BaseClass();
$proxy = new MyProxy($base);

$proxy->doSomething(); // invoke $base->doSomething();

您当然希望添加一些错误处理,例如询问代理对象是否响应__call中的给定方法,如果不响应则引发错误。您甚至可以将Proxy类设计为其他代理的基类。子代理类可以实现beforeafter方法。

缺点是您的“子类”不再实现BaseClass,这意味着如果您正在使用type-hinting并且想要求只将BaseClass类型的对象传递给功能,这种方法会失败。

答案 1 :(得分:2)

如果SubClass的方法名称可能与BaseClass的原始方法名称略有不同,则可以使用__call()编写通用包装器。如果方法名称必须匹配,我不知道如何在不手动覆盖每个方法的情况下实现目标。也许您可以使用funcall PECL来执行此操作 - 但您必须首先加载该PECL。

如果您可以创建BaseClass protected的方法,则SubClass中的__call()方法将起作用。

如果你不需要来扩展课程,@ meager的方法就完全没问题了。请注意,__ call()和call_user_func_array()会产生一定的开销。

答案 2 :(得分:0)

您可能正在寻找装饰模式:

class A
{
   function do1(){

   }
}
class DecoratorForA extends A
{
   private A original;
   public DecoratorForA( A original )
   {
      this.original = original;
   }
   function do1(){  //<-- override keyword in php?
      stuffBefore(); 
      original->do1();
      stuffAfter();      
   }
}

因为这不是你想要的,也许这个链接有帮助吗? http://code.google.com/p/php-aop/

答案 3 :(得分:0)

如果我理解你正确,你想扩展一个类,但不允许调用父类的任何方法。相反,您希望在新类中的一个方法中自己调用所有方法。

那么为什么你甚至想要继承?这听起来很像你应该为你的BaseClass创建一个适配器/装饰器。

class SubClass
{
   function magicalOverrideEveryone()
   {
      BaseClass bc = new BaseClass();
      bc.do_something();
      bc.do_something_else();
   }
}