从父类调用子方法

时间:2013-07-29 08:41:02

标签: php 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
    }

}

3 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分:1)

试试这个:

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,可由孩子调用。当孩子们被实例化时,他们会告诉父母他们希望在保存时调用的方法的名称。

如果方法存在,则使用任何参数调用它,否则会引发异常(您可以更改错误处理)。

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

答案 2 :(得分:0)

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

一般情况下:您在父级中使用的任何方法都应声明为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; 
  }
}