Принудительный вызов родительского метода - PullRequest
9 голосов
/ 04 ноября 2011

Есть ли какой-либо (или шаблон) принудительный вызов родительского метода?

У меня есть абстрактный класс, такой как:

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.
   }
}

Проблема в том, что если мы вернемся к коду через несколько месяцев и создадим еще несколько классов, таких как CSophisticated, с помощью метода validate(), существуетвероятность того, что мы можем забыть сделать вызов parent::validate() в этом методе.

Обратите внимание, что некоторые CSophisticated классы могут не иметь метода validate(), поэтому будет вызвана родительская версия.

Я понимаю, что можно просто вставить комментарий где-то, чтобы напомнить программисту, чтобы он вызывал parent::validate(), но есть ли лучший способ?Возможно, было бы неплохо использовать автоматический способ создания исключения, если вызов parent::validate() не был выполнен в методе validate().

Ответы [ 2 ]

10 голосов
/ 04 ноября 2011

Вы можете выполнить вызов с помощью следующего:

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 не мой язык выбора), но принцип применим к большинству языков ООП.

ДОПОЛНИТЕЛЬНОЕ ОБЪЯСНЕНИЕ:

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)
9 голосов
/ 04 ноября 2011

Вы ищете Шаблонный шаблон шаблон.
Этот шаблон позволяет вам каким-либо образом изменить операцию посредством подкласса, но гарантирует, что базовый класс всегда задействован.

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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...