从父类调用子方法


Call child method from parent class

我有一个class,它被其他几个class用作扩展程序,在一个实例中,父class的方法需要回调子class的方法。有办法做到这一点吗?

我意识到PHP包含abstract类和函数,但要求每个子类都有声明的abstract函数,在这种情况下我不需要。

例如(这些是示例,而不是现实生活)-

Class parent{
    function on_save_changes(){
        some_parent_function();
        if($_POST['condition'] === 'A') :
            // Call 'child_1_action()'
        elseif($_POST['condition'] === 'B') :
            // Call 'child_2_action()'
        endif       
        some_other_parent_function();
    }
    function some_parent_function(){
        // Do something here, required by multiple child Classes
    }
}
Class child_1 Extends parent{
    function __construct(){
        $this->on_save_changes();
    }
    function child_1_action(){
        // Do something here, only every required by this child Class
    }
}
Class child_2 Extends parent{
    function __construct(){
        $this->on_save_changes();
    }
    function child_2_action(){
        // Do something here, only every required by this child Class
    }
}

您只需简单地调用子方法就可以做到这一点,例如:

if($_POST['condition'] === 'A') :
    $this->some_parent_function();
    $this->child_1_action();

但是,您应该避免这样做在父类中放入只调用子类中存在的方法的检查是一种非常糟糕的设计气味。总有一种方法可以通过利用众所周知的设计模式或简单地更好地思考类层次结构来以更结构化的方式做事。

您可以考虑的一个非常简单的解决方案是在父类中将所有这些方法实现为无操作;每个子类都可以覆盖它感兴趣的方法(并为其提供实现)。这是一个有点机械的解决方案,因此无法知道它是否真的是您的情况下的最佳方法,但即使如此,它也比技术上不保证存在的冷调用方法要好得多。

试试这个:

class ParentClass{
    private $childActionMethod;
    public function on_save_changes(){
        if(method_exists($this, $this->childActionMethod)) {
            call_user_func_array(array($this, $this->childActionMethod), func_get_args());
        }
        else {
            throw new Exception('Child Method has not been set');
        }
    }
    protected function setChildActionMethod($methodName) {
        $this->childActionMethod = $methodName;
    }
}
class ChildClass1 extends ParentClass{
    function __construct(){
        $this->setChildActionMethod('child_1_action');
    }
    function child_1_action(){
        echo('Hello First World<br />');
    }
}
class ChildClass2 extends ParentClass{
    function __construct(){
        $this->setChildActionMethod('child_2_action');
    }
    function child_2_action(){
        echo('Hello Second World<br />');
    }
}
$child1 = new ChildClass1();
$child1->on_save_changes();
// Hello First World
$child2 = new ChildClass2();
$child2->on_save_changes();
// Hello Second World

父类具有受保护的方法setChildActionMethod,可由子类调用。当子级被实例化时,他们会告诉父级他们希望它在保存时调用的方法的名称。

如果该方法存在,则使用任何参数调用它,或者抛出异常(您可以更改错误处理)。

我确信这种模式有一个名字,但我不确定它叫什么。

如果需要在父类中创建一些操作序列,则可以使用"模板方法"模式,子类应该以某种预定义的方式自行实现这些操作序列。但是您应该避免引用未来定义的任意方法。

一般来说:在父级中使用的任何方法都应该声明为abstract或具有默认实现。子级将覆盖这些方法。

abstract class parent{
  function on_save_changes(){
    some_parent_function();
    some_child_action();
    some_other_parent_function(); // added to follow changes of question
  }
  function some_parent_function(){
    // Do something here, required by multiple child Classes
  }
  abstract public function some_child_action();
}
class child_1 Extends parent{
  function some_child__action(){
    if($_POST['condition'] === 'A') : 
      // Do something here, only every required by this child Class
    endif;
   }
}
class child_2 Extends parent{
  function some_child_action(){
    if($_POST['condition'] === 'B') :
      // Do something here, only every required by this child Class
    endif; 
  }
}