PHP:如何从父类调用子类的function
我如何从父类调用子类的function? 考虑这个:
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 !!"; } }
这就是抽象类的用途。 一个抽象类基本上说:谁从我这里inheritance,必须有这个function(或这些function)。
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();
好的,这个答案是非常晚,但为什么没有人想到这个?
Class A{ function call_child_method(){ if(method_exists($this, 'child_method')){ $this->child_method(); } } }
该方法在扩展类中定义:
Class B extends A{ function child_method(){ echo 'I am the child method!'; } }
所以用下面的代码:
$test = new B(); $test->call_child_method();
输出将是:
I am a child method!
我使用它来调用可以由子类定义的钩子方法,但不一定是。
从技术上说,你不能从一个鲸鱼实例(父)调用一个鱼实例(child),但是由于你正在处理inheritance,myFunc()将会在你的fish实例中可用,所以你可以调用$yourFishInstance->myFunc()
直。
如果你正在引用模板方法模式 ,那么$this->test()
作为方法体。 从fish实例调用myFunc()
会将调用委托给fish实例中的test()
。 但是,再次,从鲸鱼实例到鱼实例的呼叫。
在旁注中,鲸鱼是哺乳动物,而不是鱼;)
好吧,这个问题有太多的错误,我真的不知道从哪里开始。
首先,鱼不是鲸鱼,鲸鱼也不是鱼。 鲸鱼是哺乳动物。
其次,如果你想从父类中不存在的父类中调用一个函数,那么你的抽象是严重的缺陷,你应该从头开始重新思考。
第三,在PHP中,你可以这样做:
function myfunc() { $this->test(); }
在whale
一个实例中,它会导致一个错误。 在fish
的情况下,它应该工作。
从PHP 5.3开始,您可以使用static关键字来调用被调用类的方法。 即:
<?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(); ?>
上面的例子会输出:B
来源: PHP.net /晚期静态绑定
我会去抽象类….
但在PHP中,您不必使用它们来使其工作。 即使调用父类的构造函数也是一个“正常的”方法调用,并且这个对象在这个时候是完全“可操作的”,也就是说,$这个“知道”所有成员,是否inheritance。
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;
版画
Bar::__construct() Foo::__construct() Bar::init()
即使Foo类对函数init()没有任何了解,也可以调用该方法,因为查找是基于$ this的引用。
这是技术方面。 但是你真的应该强制执行这个方法,或者把它抽象(迫使后代来实现)或者提供一个可以被覆盖的默认实现。
我知道这可能对你来说有点晚了,但我也必须解决这个问题。 为了帮助他人理解为什么有时候这是一个要求,这里是我的例子:
我正在为一个应用程序构build一个MVC框架,我有一个基础控制器类,由每个控制器类扩展。 每个控制器将有不同的方法,取决于控制器需要做什么。 例如,mysite.com/event会加载事件控制器。 mysite.com/event/create将加载事件控制器并调用“create”方法。 为了规范创build函数的调用,我们需要基类控制器类来访问子类的方法,这对每个控制器都是不同的。 所以在代码方面,我们有父类:
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(); } }
}
那么孩子class:
class wordcontroller extends controller { public function add() { echo "Inside Add"; } public function edit() { echo "Inside Edit"; } public function delete() { echo "Inside Delete"; }
}
所以在我的情况下,解决scheme是将子实例本身作为parameter passing回父类。
你能做到的唯一方法就是反思 。 但是,reflection是昂贵的,只能在必要时使用。
真正的问题在于父类不应该依赖子类方法的存在。 这是OOD的指导原则,表明你的devise存在严重的缺陷。
如果你的父类是依赖于一个特定的孩子,那么它不能被任何其他可能扩展它的子类使用。 亲子关系从抽象到具体,而不是相反。 如果需要的话,将父类中所需的函数放在父类中,并将其覆盖在子类中将会更好。 像这样的东西:
class whale { function myfunc() { echo "I am a ".get_class($this); } } class fish extends whale { function myfunc() { echo "I am always a fish."; } }
如果鲸鱼没有延长呢? 这个函数调用会导致什么结果? 不幸的是,没有办法做到这一点。
哦,还有一条鱼扩大了鲸鱼吗? 鱼是鱼,鲸是哺乳动物。
这很简单。 你可以做到这一点没有抽象类。
class whale { function __construct() { // some code here } /* Child overridden this function, so child function will get called by parent. I'm using this kind of techniques and working perfectly. */ function test(){ return ""; } function myfunc() { $this->test(); } } class fish extends whale { function __construct() { parent::construct(); } function test() { echo "So you managed to call me !!"; } }