我正在学习PHP,刚从中级开始。下面是类层次结构 -
FamilyTree
|
|
Grandparents
|
|
Parents
Parents
有一个名为$dob
其余属性继承自Grandparents
我能够重载set_values()
因为它们的参数数量不同,我如何重载display_values()
因为它不需要任何论点?
这是代码:
<?php
class FamilyTree {
protected $name;
protected $sex;
protected $married;
protected $number_of_kids;
public function display_values() {
echo $this->name . "<br />";
echo $this->sex . "<br />";
echo $this->married . "<br />";
echo $this->number_of_kids . "<br />";
}
}
class Grandparents extends FamilyTree {
public function set_values($name, $sex, $married, $number_of_kids) {
$this->name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
}
}
class Parents extends Grandparents {
private $dob;
public function __call($function_name, $arguments) {
if($function_name == 'set_values' && count($arguments) == 5) {
$this->$name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
$this->dob = $dob;
}
}
}
$gp = new Grandparents();
$gp->set_values("James", "Male", 'yes', 5);
$p = new Parents();
$p->set_values("Samuel", "Male", 'yes', 2, '2/5/1974');
$gp->display_values();
抱歉让您失望,但您未能成功"重载"该方法。
如果您仔细查看您的实现,如果__call
:
public function __call($function_name, $arguments) {
if($function_name == 'set_values' && count($arguments) == 5) {
$this->$name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
$this->dob = $dob;
}
}
你会注意到
-
$this->$name
应该$this->name
-
$name
、$sex
、$married
、$number_of_kids
和$dob
都是未定义的,应该$arguments[0]
$arguments[4]
。
但是你的__call
实现根本不会被调用,因为PHP只是将太多的参数丢弃给用户定义的函数。
相反,您可以做的是覆盖该函数并使用 parent::
调用父实现:
public function set_values($name, $sex, $married, $number_of_kids, $dob = '') {
parent::set_values($name, $sex, $married, $number_of_kids);
$this->dob = $dob;
}
我只是将$dob
初始化为空字符串,否则它会默认NULL
。
作为旁注,如果你想提供一个比原始实现更少的参数的新实现,你也可以使用默认参数来做到这一点:
public function set_values($name, $sex, $married, $number_of_kids = 0) {
parent::set_values($name, $sex, $married, $number_of_kids);
}
然后可以使用 3 或 4 个参数调用。
对于更复杂的组合,请使用每个参数的默认参数声明新实现(以使其与父实现兼容),并使用func_get_args
来处理或重定向调用。
不过,覆盖display_values
很简单,因为参数的数量是相同的:
public function display_values() {
parent::display_values();
echo $this->dob . "<br />";
}
因此,完整地,您的代码将如下所示:
<?php
class FamilyTree {
protected $name;
protected $sex;
protected $married;
protected $number_of_kids;
public function display_values() {
echo $this->name . "<br />";
echo $this->sex . "<br />";
echo $this->married . "<br />";
echo $this->number_of_kids . "<br />";
}
}
class Grandparents extends FamilyTree {
public function set_values($name, $sex, $married, $number_of_kids) {
$this->name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
}
}
class Parents extends Grandparents {
private $dob;
public function set_values($name, $sex, $married, $number_of_kids, $dob = '') {
parent::set_values($name, $sex, $married, $number_of_kids);
$this->dob = $dob;
}
public function display_values() {
parent::display_values();
echo $this->dob . "<br />";
}
}
$gp = new Grandparents();
$gp->set_values("James", "Male", 'yes', 5);
$p = new Parents();
$p->set_values("Samuel", "Male", 'yes', 2, '2/5/1974');
$gp->display_values();
$p->display_values();
对于方法重载,签名和方法名称必须相同。没有这两个,它不会被视为方法重载。在这种情况下,is不是重载,而是一个单独的方法。您可以简单地通过此display_values($name、$、$married、$number_of_kids)重载并设置所有值
除非我误解了你,否则在这种情况下,你不会通过类父级中的__call set_values过载。若要重载,该方法必须不可访问。
class Parents extends Grandparents {
private $dob;
public function __call($function_name, $arguments) {
echo 'called';
if($function_name == 'set_values' && count($arguments) == 5) {
$this->$name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
$this->dob = $dob;
}
}
}
这不会打印 $p->set_values 的"called"("Samuel", "Male", 'yes', 2, '2/5/1974');。
若要重写父方法必须无法访问的方法,参数的数量无关紧要,请参阅以下示例:
<?php
class FamilyTree {
protected $name;
protected $sex;
protected $married;
protected $number_of_kids;
private function display_values() {
echo $this->name . "<br />";
echo $this->sex . "<br />";
echo $this->married . "<br />";
echo $this->number_of_kids . "<br />";
}
}
class Grandparents extends FamilyTree {
private function set_values($name, $sex, $married, $number_of_kids) {
$this->name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
}
private function drawMe($a)
{}
}
class Parents extends Grandparents {
private $dob;
public function __call($function_name, $arguments) {
echo 'Args: ' . count($arguments);
echo ' | Function name: ' . $function_name;
if($function_name == 'set_values' && count($arguments) == 5) {
$this->$name = $name;
$this->sex = $sex;
$this->married = $married;
$this->number_of_kids = $number_of_kids;
$this->dob = $dob;
}
}
}
$p = new Parents();
$p->display_values();
echo '<br><br>';
$p->set_values("Samuel", "Male", 'yes', 2, '2/5/1974');
这将打印:
参数: 0 |函数名称:display_values
参数: 5 |函数名称:set_values