简体   繁体   English

从父类调用子方法

[英]Call child method from parent class

I have a Class that is used as an extender by several other Classes, and in one instance, a method from the parent Class needs to call back to a method from the child Class. 我有一个类被其他几个类用作扩展器,在一个实例中,父类的方法需要从子类回调一个方法。 Is there a way of doing this? 有办法做到这一点吗?

I realise PHP contains abstract Classes and functions, but would require each child Class to have the declared abstract function(s), which I do not require in this case. 我意识到PHP包含abstract类和函数,但是要求每个子类都具有声明的abstract函数,在这种情况下我不需要。

For example ( these are examples, not real life ) - 例如( 这些是例子,而不是现实生活 ) -

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
    }

}

You can do this by just simply calling the child method, eg: 您只需调用子方法即可完成此操作,例如:

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

However, you should avoid doing this. 但是,你应该避免这样做。 Putting checks in the parent that call methods only existing in a child class is a very bad design smell. 将检查放在调用仅存在于子类中的方法的父项中是一种非常糟糕的设计气味。 There is always a way to do things in a more structured manner by utilizing well-known design patterns or simply thinking the class hierarchy through better. 通过利用众所周知的设计模式或简单地通过更好地思考类层次结构,总有一种方法可以以更有条理的方式进行。

A very simple solution you can consider is implementing all of these methods in the parent class as no-ops; 您可以考虑的一个非常简单的解决方案是在父类中将所有这些方法实现为no-ops; each child class can override (and provide implementation for) the method that it's interested in. This is a somewhat mechanical solution so there's no way to know if it's indeed the best approach in your case, but even so it's much better than cold-calling methods that technically are not guaranteed to exist. 每个子类都可以覆盖(并提供实现)它感兴趣的方法。这是一个有点机械的解决方案,因此无法知道它是否确实是您的情况下的最佳方法,但即使如此,它也比冷调用好得多技术上不保证存在的方法。

Try this: 尝试这个:

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

The parent class has the protected method setChildActionMethod , callable by the children. 父类具有受保护的方法setChildActionMethod ,可由子setChildActionMethod调用。 When the children are instantiated, they tell the parent the name of the method they would like it to call on save. 当孩子们被实例化时,他们会告诉父母他们希望在保存时调用的方法的名称。

If the method exists then it is called with any arguments, or it throws an exception (you can change the error handling). 如果该方法存在,则使用任何参数调用它,或者它抛出异常(您可以更改错误处理)。

I'm sure theres a name for this pattern, but I am unsure what it is called. 我确定这个模式有一个名字,但我不确定它叫什么。

You may use "Template method" pattern, if you need to create some action sequence in parent that child classes should implement on their own but in some predefined manner. 您可以使用“模板方法”模式,如果您需要在父类中创建一些动作序列,子类应该以某种预定义的方式实现。 But you should avoid referring to future defined arbitrary methods. 但是你应该避免引用未来定义的任意方法。

In general: any method you use in your parent should be declared either as abstract or have default implementation. 通常:您在父级中使用的任何方法都应声明为abstract或具有默认实现。 Children will override these methods. 孩子们会覆盖这些方法。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM