子类构造函数调用的PHP覆盖方法

3

我在尝试理解父类和子类之间的关系时,玩弄了一些类。 我设置了一个构造函数来调用初始化方法。 然后当我在子类中添加一个init方法时,它会覆盖父类的init方法,不是吗? 但实际情况是两个方法都被调用了。

为了测试这一点,我编写了一个名为Model的类和一个子类Instance。 这是代码:

$try = new Instance;
echo $try;

class Model{

    public function __construct(){    
        $this->init();
    }

    public function init()
    {        
        return $this->className();   
    }

    public function __toString()
    {
        return $this->className();
    }

    public static function className()
    {
        return get_called_class();
    }

}

class Instance extends Model
{
    public function init()
    {
        echo "tada! ";
     }
}

提供以下输出:
tada! Instance.

在类模型中,我使用了魔术方法__toString()将类名作为字符串返回。父类的构造函数调用父init()方法,在这种情况下,它会输出类名。

我的理解是,如果我编写一个子类,例如Instance类,并且具有一个init()方法,它将覆盖父init()方法,但实际上并非如此。在这种情况下,它返回了两个init方法,我不知道为什么。有人能解释一下吗?

4个回答

3
事实上 -
当你使用"$try = new Instance;"来实例化类"Instance"的对象时,它会调用构造函数,由于子类覆盖了"init"方法,所以它打印出"tada!"。
在另一行中,你使用"echo $try;"输出类"Instance"的对象,并且父类中实现了一个魔术方法__toString()。因此它打印出类名 "Instance"。
你只能运行$try = new Instance;,这样只会打印出"tada!"。

2
"contractor"? 你是指构造函数 :) - vascowhite
谢谢您的回答,它帮助我理解了它的工作原理。 - Evercode

2
你正在运行两个不同的命令。首先,你使用$try = new Instance;实例化类,这会调用__construct。父类中的__construct()会调用init(),该方法使用子类init()并返回tada!。在子类中创建一个空构造函数来覆盖父构造函数。
第二个命令是当你使用__toString()输出类:echo $try;,它会输出由父类定义的Instance
你也可以通过使用以下方式向父构造函数添加内容:
public function __construct() {
  ...code...
  parent::__construct();
  ...code...
}

谢谢您的回答和建议,它们帮助我理解了它的工作原理。 - Evercode

0

原因:

由于您的子类没有定义任何构造函数,父类构造函数将被触发,这就是为什么您会得到那个输出。

解释:

当您执行

$try = new Instance;

父类构造函数被触发,它将调用init(),后者又调用className(),后者执行get_called_class(),因此最终会调用子类中的init(),并且你会首先得到"tada!"的输出。
当你这样做时...
echo $try;

__toString()方法被调用并返回类名Instance

所以基本上,如果你的子类有一个constructor构造函数,你将不会得到输出"tada!"


0
在这种情况下,它返回两个init方法。
不,它没有;
“tada!”由Instance :: init()回显,“Instance”由Model :: __toString()回显。

所以,为了百分之百的清晰度,在定义魔术_toString()方法时,如果对象本身被回显,那么在该方法中定义的任何内容都将被打印,就像我用echo $try;一样。谢谢大家的帮助。 - Evercode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接