2013-07-29 37 views
3

我有被其他几类用作扩展一个类,并在一个事例,从父类的方法需要回调从子类中的方法。有没有办法做到这一点?调用子方法与父

我意识到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 
    } 

} 
+2

还有另一个线程在stackoverflow与相同的查询: http://stackoverflow.com/questions/1944827/php-how-to-call-function-of-a-child-class-from-parent-class – maxxon15

+0

请参阅我的问题的第二段,解释为什么在这种情况下,该答案不适合我。 –

回答

7

你可以只是简单的调用子方法,如这样做:

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

然而,你应该避免这样做。把调查放在只调用子类中存在的方法的父级是一种非常糟糕的设计气味。通过利用着名的设计模式或者仅仅通过更好地思考类层次结构,总有一种方法可以以更加结构化的方式进行。

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

+0

+1不良设计气味提示。 – moonwave99

+0

感谢您的回复。直接从父项调用子方法不起作用(调用未定义的方法错误)。我认为在这种情况下我会做的是覆盖'on_save_changes()'方法。我将不得不复制一些功能开始,但我很欣赏你所说的关于寻找以更好的方式构建类。 –

+0

@DavidGard:如果你得到这样的错误,这意味着你正试图调用错误类型的子对象的方法。虽然这肯定是调用逻辑(或者应该实现一个方法但没有的子类)中的一个错误,但这也可以解释为什么你不应该首先这样做。 – Jon

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; 
    } 
} 
+0

但我应该注意到,即使在这种情况下,由于混合了具有显式分支内部的类层次结构,所以它的设计很糟糕。 – dmitry

+0

感谢您的回复。所以在这种情况下,我必须去'child-> parent-> child-> parent'来获得我需要的功能吗?从技术上讲,它会工作,所以我会考虑这种技术... –

+0

你明白什么是“抽象”的方法?只是要确定。你创建模板(on_save_changes)和一些逻辑框架,以及你不能在父项中实现的所有方法,只是抽象并留下来由孩子实现。这是“模板方法”模式。 – dmitry

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,深受孩子们调用。当孩子们被实例化时,他们会告诉父母他们想要调用保存的方法的名称。

如果那么该方法存在它被称为有任何参数,或者抛出一个异常(你可以改变错误处理)。

我敢肯定,那里有一个名字为这种模式,但我不能确定它叫什么。

+0

有趣的接近它的方式。虽然技术上我认为这会起作用,但如果可能的话,我宁愿避免,因为它有点混乱。谢谢你的提示。 –

+0

你不会找到一个干净的解决方案,父类不应该知道派生类的任何东西,除了它声明的属性和方法的“存在”。 – Flosculus