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
    }

}
4

3 回答 3

7

你可以通过简单地调用子方法来做到这一点,例如:

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

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

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

于 2013-07-29T08:43:59.680 回答
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,可由子类调用。当孩子被实例化时,他们告诉父母他们希望它在保存时调用的方法的名称。

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

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

于 2013-07-29T09:03:38.960 回答
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; 
  }
}
于 2013-07-29T08:50:49.837 回答