方法重写
本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 23 课,共 91 课。
有时,继承自父类的方法不太符合子类的需求。方法重写可以让子类为父类中已有的方法提供自己的实现。
要重写一个方法,只需在子类中定义一个与父类方法同名的方法:
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
return "$this->name makes a sound";
}
}
class Cat extends Animal {
public function speak() {
return "$this->name says meow";
}
}
$cat = new Cat("Whiskers");
echo $cat->speak();
输出:
Whiskers says meowCat 类完全用自己的版本替换了父类的 speak() 方法。当你对猫对象调用 speak() 时,PHP 会使用子类的实现。
你还可以将 parent:: 与自己的逻辑结合起来,扩展父类的行为:
<?php
class Dog extends Animal {
public function speak() {
return parent::speak() . " - woof woof!";
}
}
$dog = new Dog("Rex");
echo $dog->speak();
输出:
Rex makes a sound - woof woof!关键点:方法重写允许子类自定义继承的行为。你可以完全替换一个方法,也可以使用 parent:: 在原有实现的基础上进行扩展。
挑战
简单我们来构建一个通知系统,演示子类如何通过方法重写完全替换或扩展父类的方法。
你将创建三个协同工作的文件,用来发送不同类型的通知,每种通知都有自己的行为:
Notification.php:定义一个Notification类,作为所有通知类型的基类。它应有一个公共$recipient属性,以及一个接收并设置收件人的构造函数。添加一个send($message)方法,返回"Sending to [recipient]: [message]"。UrgentNotification.php:定义一个继承自Notification的UrgentNotification类。在文件顶部包含 Notification 文件。这个类应完全重写send($message)方法,使其返回"URGENT to [recipient]: [message]!!!":注意 "URGENT" 前缀和末尾的感叹号。这展示了如何完全替换父类的行为。LoggedNotification.php:定义一个继承自Notification的LoggedNotification类。在文件顶部包含 Notification 文件。这个类应重写send($message)方法,但要基于父类的实现来构建:调用parent::send($message),并在结果后追加" [logged]"。这展示了如何扩展而非替换原有行为。
在 main.php 中,包含这三个通知类文件。你将收到两个输入:收件人姓名和要发送的消息。为每种通知类型创建一个实例(都使用同一个收件人),然后分别对每个实例调用 send() 并传入消息。按以下顺序将每个结果单独打印在一行中:普通通知、紧急通知,然后是已记录的通知。
这个挑战展示了方法重写的两种做法:UrgentNotification 用自己的格式完全替换父类的逻辑,而 LoggedNotification 使用 parent:: 保留原有行为并在此基础上添加内容。
亲手试试
<?php
require_once 'Notification.php';
require_once 'UrgentNotification.php';
require_once 'LoggedNotification.php';
// 读取输入
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: 为每种通知类型各创建一个实例(都使用同一个接收者)
// TODO: 对每个通知调用 send(),传入消息
// 按以下顺序打印结果,每个结果单独占一行:
// 1. 普通通知
// 2. 紧急通知
// 3. 带日志的通知
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: PHP 在线编译器