强制调用父方法

时间:2011-11-04 07:14:16

标签: php oop design-patterns

无论如何(或模式)是否强制调用父方法?

我有一个像这样的抽象类:

abstract class APrimitive{
   public function validate(){
      //Do some stuff that applies all classes that extend APrimitive
   }
}

然后我有一些扩展到APrimitive“base”的类:

class CSophisticated extends APrimitive{

   public function validate(){
       //First call the parent version:
       parent::validate();

       //Then do something more sophisticated here.
   }
}

问题在于,如果我们在几个月后回到代码中,并使用validate()方法创建一些类似CSophisticated的类,我们可能会忘记拨打电话该方法中parent::validate()

请注意,某些CS复杂类可能没有validate()方法,因此将调用父版本。

我知道可以在某个地方发表评论,提醒程序员拨打parent::validate(),但是有更好的方法吗?如果未在parent::validate()方法中调用validate(),那么抛出异常的自动方式可能会很好。

2 个答案:

答案 0 :(得分:10)

您可以使用以下内容强制执行此操作:

abstract class APrimitive{
   final public function validate(){
      //do the logic in validate
      overrideValidate();
   }
   protected function overrideValidate(){
   }
}

class CSophisticated extends APrimitive{

   protected function overrideValidate(){

   }
}

现在只允许调用validate,这将调用您的重写方法。语法可能稍微偏离(PHP不是我选择的语言)但该原则适用于大多数OOP语言。

进一步解释:

abstract class APrimitive{
   public function validate(){
      echo 'APrimitive validate call.';
      overrideValidate();
   }
   protected function overrideValidate(){
   }
}

class CSophisticated extends APrimitive{

   protected function overrideValidate(){
       echo 'CSophisticated call.';
   }
}

CSophisticated foo;
foo.overrideValidate(); //error - overrideValidate is protected
foo.validate(); //

输出:

APrimitive validate call.
CSophisticated call.

函数调用基本上执行以下操作:

foo.validate() -> APrimitive.validate() -> ASophisticated.overrideValidate() (or APrimitive.overrideValidate() if it wasn't overriden)

答案 1 :(得分:9)

您正在寻找The Template Method模式 此模式允许您通过子类化以某种方式修改操作,但确保始终涉及基类。

class Base {
    //declared final so it can't be overridden
    public final function validate() {

        //perform base class operations here

        //then forward to the sub class
        $this->doValidate();

        //do some more base class stuff here if needed

    }

    //override this method to alter validate operation
    protected function doValidate(){
        //no-op in base
    }
}

class Sub {
    protected function doValidate() {
        //if required
        //make the sub-class contribution to validate here
    }
}