PHP:如何从父类调用子类的函数
如何从父类调用子类的函数? 考虑这一点:PHP:如何从父类调用子类的函数,php,inheritance,Php,Inheritance,如何从父类调用子类的函数? 考虑这一点: 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::
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 !!";
}
}
如果鲸鱼没有延伸呢?那个函数调用会产生什么结果?不幸的是,没有办法做到这一点
哦,鱼会延伸鲸鱼吗?鱼是鱼,鲸鱼是哺乳动物 好吧,这个问题有太多问题,我真的不知道从哪里开始 首先,鱼不是鲸鱼,鲸鱼也不是鱼。鲸鱼是哺乳动物 其次,如果您想从父类中不存在的父类调用子类中的函数,那么您的抽象存在严重缺陷,您应该从头开始重新考虑它 第三,在PHP中,您可以执行以下操作:
function myfunc() {
$this->test();
}
在
whale
的实例中,它将导致错误。在fish
的例子中,它应该可以工作。唯一可以做到这一点的方法是通过。然而,反射是昂贵的,应该只在必要时使用
这里真正的问题是父类永远不应该依赖于子类方法的存在。这是面向对象设计的指导原则,表明您的设计中存在严重缺陷
如果父类依赖于特定的子类,则任何其他可能扩展它的子类都不能使用它。父子关系从抽象到具体,而不是相反。您最好将所需函数放在父类中,必要时在子类中重写它。大概是这样的:
class whale
{
function myfunc()
{
echo "I am a ".get_class($this);
}
}
class fish extends whale
{
function myfunc()
{
echo "I am always a fish.";
}
}
从技术上讲,您不能从鲸鱼实例(父实例)调用鱼实例(子实例),但由于您处理的是继承,myFunc()在您的鱼实例中仍然可用,因此您可以直接调用
$yourFishInstance->myFunc()
如果您正在引用,那么只需编写$this->test()
作为方法体。从fish实例调用myFunc()
将把调用委托给fish实例中的test()
。但同样,不要从鲸鱼实例调用鱼实例
另一方面,鲸鱼是哺乳动物而不是鱼;) 这就是我们的目的。一个抽象类基本上说:从我继承的人必须拥有这个函数(或这些函数)
我会选择抽象类……
但是在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;
印刷品
Bar::__construct()
Foo::__construct()
Bar::init()
i、 e.即使类Foo对函数init()一无所知,它也可以调用该方法,因为查找是基于$this所引用的内容。这是技术方面。但您确实应该通过使该方法抽象(强制子代实现)或提供可以覆盖的默认实现来强制实现该方法 我知道这对你来说可能有点晚了,但我也不得不绕开这个问题。为了帮助其他人理解为什么这有时是一项要求,以下是我的示例: 我正在为一个应用程序构建一个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();
}
}
}
然后是儿童班:
class wordcontroller extends controller {
public function add() {
echo "Inside Add";
}
public function edit() {
echo "Inside Edit";
}
public function delete() {
echo "Inside Delete";
}
}
因此,在我的例子中,解决方案是将子实例本身作为参数传递回父类 由于PHP5.3,您可以使用static关键字从被调用的类调用方法。i、 e:
<?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
来源:好吧,这个答案已经很晚了,但是为什么没有人想到这个呢
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!
我用它来调用钩子方法,钩子方法可以由一个子类定义,但不一定是这样。非常简单。您可以在没有抽象类的情况下实现这一点
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 !!";
}
}
即使这是一个老问题,这也是我使用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);
}
}
使用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);
}
如果子类中存在方法,则将从父类调用该方法(如果存在,则作为可选回调)
从鲸鱼实例您不能调用此函数。但是从鱼的例子中,你可以
不管怎样,我无法理解你的答案,你能建议一个替代方案吗?这是不符合逻辑的。如果鲸鱼没有子类,它就不会被扩展,因此没有方法从中调用。@Marius“鱼是鱼,鲸鱼是哺乳动物。”---这跟什么有什么关系?这是一个类名。代码有效吗?这才是真正的问题。因为你的回答可能只是一个评论(它没有试图以任何方式解决这个问题),而且因为你非常傲慢,我将对这个答案投反对票。我怀疑这是否可以通过反思来实现。Whale必须在某个地方对Fish进行硬编码。这只是一个示例,伙计,我不会在任何地方实现这些名称:)我知道我放置了错误的类名,但这只是一个示例,我不会在任何地方实现它。从逻辑上看,fish
应该是父类,whale
应该是子类;)@DaNieL也许fish应该是子类,因为它位于
//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);
}
<?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'));
function myfunc()
{
static::test();
}