PHP:如何从父类调用子类的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1944827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP: How to call function of a child class from parent class
提问by Sarfraz
How do i call a function of a child class from parent class? Consider this:
如何从父类调用子类的函数?考虑一下:
class whale
{
function __construct()
{
// some code here
}
function myfunc()
{
// how do i call the "test" function of fish class here??
}
}
class fish extends whale
{
function __construct()
{
parent::construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
回答by FlorianH
That's what abstract classesare for. An abstract class basically says: Whoever is inheriting from me, must have this function (or these functions).
这就是抽象类的用途。一个抽象类基本上说:从我那里继承的人,必须拥有这个功能(或这些功能)。
abstract class whale
{
function __construct()
{
// some code here
}
function myfunc()
{
$this->test();
}
abstract function test();
}
class fish extends whale
{
function __construct()
{
parent::__construct();
}
function test()
{
echo "So you managed to call me !!";
}
}
$fish = new fish();
$fish->test();
$fish->myfunc();
回答by Christian Engel
Okay, this answer is VERY late, but why didn't anybody think of this?
好吧,这个答案很晚了,但为什么没有人想到这一点?
Class A{
function call_child_method(){
if(method_exists($this, 'child_method')){
$this->child_method();
}
}
}
And the method is defined in the extending class:
该方法在扩展类中定义:
Class B extends A{
function child_method(){
echo 'I am the child method!';
}
}
So with the following code:
所以使用以下代码:
$test = new B();
$test->call_child_method();
The output will be:
输出将是:
I am a child method!
I use this to call hook methods which canbe defined by a child class but don't have to be.
我用它来调用可以由子类定义但不必如此的钩子方法。
回答by Gordon
Technically, you cannot call a fish instance (child) from a whale instance (parent), but since you are dealing with inheritance, myFunc() will be available in your fish instance anyway, so you can call $yourFishInstance->myFunc()directly.
从技术上讲,您不能从鲸鱼实例(父)中调用鱼实例(子),但是由于您正在处理继承,因此 myFunc() 无论如何都将在您的鱼实例中可用,因此您可以$yourFishInstance->myFunc()直接调用。
If you are refering to the template method pattern, then just write $this->test()as the method body. Calling myFunc()from a fish instancewill delegate the call to test()in the fish instance. But again, no calling from a whale instance to a fish instance.
如果您指的是模板方法模式,则只需将其写$this->test()为方法主体。myFunc()从fish 实例调用会将调用委托给test()fish 实例。但同样,没有从鲸鱼实例到鱼实例的调用。
On a sidenote, a whale is a mammal and not a fish ;)
在旁注中,鲸鱼是哺乳动物而不是鱼;)
回答by cletus
Ok, well there are so many things wrong with this question I don't really know where to start.
好吧,这个问题有很多问题,我真的不知道从哪里开始。
Firstly, fish aren't whales and whales aren't fish. Whales are mammals.
首先,鱼不是鲸鱼,鲸鱼也不是鱼。鲸鱼是哺乳动物。
Secondly, if you want to call a function in a child class from a parent class that doesn't exist in your parent class then your abstraction is seriously flawed and you should rethink it from scratch.
其次,如果您想从父类中不存在的父类调用子类中的函数,那么您的抽象存在严重缺陷,您应该从头开始重新考虑。
Third, in PHP you could just do:
第三,在 PHP 中你可以这样做:
function myfunc() {
$this->test();
}
In an instance of whaleit will cause an error. In an instance of fishit should work.
在whale它的实例中会导致错误。在fish它的一个实例中应该可以工作。
回答by Agustin
Since PHP 5.3 you can use the static keyword to call a method from the called class. i.e.:
从 PHP 5.3 开始,您可以使用 static 关键字从被调用的类中调用方法。IE:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
The above example will output: B
上面的例子将输出:B
source: PHP.net / Late Static Bindings
回答by VolkerK
I'd go with the abstract class....
but in PHP you don't have touse them to make it work. Even the invocation of the parent class' constructor is a "normal" method call and the object is fully "operational" at this point, i.e. $this "knows" about all the members, inherited or not.
我会用抽象类去....
但是在PHP你不必须使用它们,使之工作。甚至对父类的构造函数的调用也是一个“正常”的方法调用,此时对象是完全“可操作的”,即 $this “知道”所有成员,无论是否继承。
class Foo
{
public function __construct() {
echo "Foo::__construct()\n";
$this->init();
}
}
class Bar extends Foo
{
public function __construct() {
echo "Bar::__construct()\n";
parent::__construct();
}
public function init() {
echo "Bar::init()\n";
}
}
$b = new Bar;
prints
印刷
Bar::__construct()
Foo::__construct()
Bar::init()
i.e. even though class Foodoesn't know anything about a function init()it can call the method since the lookup is based on what $this is a reference to.
That's the technical side. But you really should enforce the implementation of that method by either making it abstract (forcing descendants to implement it) or by providing a default implementation that can be overwritten.
即,即使类 Foo对函数 init()一无所知,它也可以调用该方法,因为查找是基于 $this 所引用的内容。
这就是技术方面。但是您确实应该通过使其抽象(强制后代实现它)或通过提供可以覆盖的默认实现来强制实现该方法。
回答by rca86
I know this is probably a bit late for you, but I had to get around this problem as well. To help others understand why this is sometimes a requirement, here's my example:
我知道这对你来说可能有点晚了,但我也必须解决这个问题。为了帮助其他人理解为什么有时需要这样做,这是我的示例:
I'm building an MVC framework for an application, I have a base controller class, which is extended by each individual controller class. Each controller will have different methods, depending on what the controller needs to do. Eg, mysite.com/event would load the event controller. mysite.com/event/create will load the event controller and call the 'create' method. In order to standardise the calling of the create function, we need the base controller class to access the methods of the child class, which will be different for every controller. So code-wise, we have the parent class:
我正在为应用程序构建 MVC 框架,我有一个基本控制器类,它由每个单独的控制器类扩展。每个控制器都有不同的方法,这取决于控制器需要做什么。例如,mysite.com/event 将加载事件控制器。mysite.com/event/create 将加载事件控制器并调用“create”方法。为了规范create函数的调用,我们需要基控制器类来访问子类的方法,每个控制器的方法都不一样。所以在代码方面,我们有父类:
class controller {
protected $aRequestBits;
public function __construct($urlSegments) {
array_shift($urlSegments);
$this->urlSegments = $urlSegments;
}
public function RunAction($child) {
$FunctionToRun = $this->urlSegments[0];
if(method_exists($child,$FunctionToRun)) {
$child->$FunctionToRun();
}
}
}
Then the child class:
然后是子类:
class wordcontroller extends controller {
public function add() {
echo "Inside Add";
}
public function edit() {
echo "Inside Edit";
}
public function delete() {
echo "Inside Delete";
}
}
So the solution in my case was to pass the child instance itself back to the parent class as a parameter.
因此,在我的情况下,解决方案是将子实例本身作为参数传递回父类。
回答by zombat
The only way you could do this would be through reflection. However, reflection is expensive and should only be used when necessary.
你能做到这一点的唯一方法是通过反射。然而,反射是昂贵的,应该只在必要时使用。
The true problem here is that a parent class should never rely on the existence of a child class method. This is a guiding principle of OOD, and indicates that there is a serious flaw in your design.
这里真正的问题是父类永远不应该依赖子类方法的存在。这是OOD的指导原则,表明您的设计存在严重缺陷。
If your parent class is dependent on a specific child, then it cannot be used by any otherchild classes that might extend it as well. The parent-child relationship goes from abstraction to specificity, not the other way around. You would be much, much better off to put the required function in the parent class instead, and override it in the child classes if necessary. Something like this:
如果你的父类依赖于一个特定的子类,那么它不能被任何其他可能扩展它的子类使用。亲子关系从抽象到具体,而不是相反。您最好将所需的函数放在父类中,并在必要时在子类中覆盖它。像这样的东西:
class whale
{
function myfunc()
{
echo "I am a ".get_class($this);
}
}
class fish extends whale
{
function myfunc()
{
echo "I am always a fish.";
}
}
回答by gpmaccari
Even if this is an old question, this is my solution using ReflectionMethod:
即使这是一个老问题,这也是我使用 ReflectionMethod 的解决方案:
class whale
{
function __construct()
{
// some code here
}
function myfunc()
{
//Get the class name
$name = get_called_class();
//Create a ReflectionMethod using the class and method name
$reflection = new \ReflectionMethod($class, 'test');
//Call the method
$reflection->invoke($this);
}
}
The benefit of using the ReflectionMethod class is that you could pass an array of arguments and check which one is needed in the method you are calling:
使用 ReflectionMethod 类的好处是您可以传递一组参数并检查您正在调用的方法中需要哪一个:
//Pass a list of arguments as an associative array
function myfunc($arguments){
//Get the class name
$name = get_called_class();
//Create a ReflectionMethod using the class and method name
$reflection = new \ReflectionMethod($class, 'test');
//Get a list of parameters
$parameters = $reflection->getParameters()
//Prepare argument list
$list = array();
foreach($parameters as $param){
//Get the argument name
$name = $param->getName();
if(!array_key_exists($name, $arguments) && !$param->isOptional())
throw new \BadMethodCallException(sprintf('Missing parameter %s in method %s::%s!', $name, $class, $method));
//Set parameter
$list[$name] = $arguments[$name];
}
//Call the method
$reflection->invokeArgs($this, $list);
}
回答by XPerez
If exists a method in the child class, method will be called from the parent class (as an optional callback if exists)
如果子类中存在方法,则从父类调用方法(如果存在,则作为可选回调)
<?php
class controller
{
public function saveChanges($data)
{
//save changes code
// Insert, update ... after ... check if exists callback
if (method_exists($this, 'saveChangesCallback')) {
$arguments = array('data' => $data);
call_user_func_array(array($this, 'saveChangesCallback'), $arguments);
}
}
}
class mycontroller extends controller
{
public function setData($data)
{
// Call parent::saveChanges
$this->saveChanges($data);
}
public function saveChangesCallback($data)
{
//after parent::saveChanges call, this function will be called if exists on this child
// This will show data and all methods called by chronological order:
var_dump($data);
echo "<br><br><b>Steps:</b><pre>";
print_r(array_reverse(debug_backtrace()));
echo "</pre>";
}
}
$mycontroller = new mycontroller();
$mycontroller->setData(array('code' => 1, 'description' => 'Example'));

