在 PHP 中重载多级继承中的函数,该函数不接受任何参数


Overloading a function in multilevel inheritence in PHP that doesn't take any arguments

我正在学习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