Menu
CoddyTech

方法重写

本课属于 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 meow

Cat 类完全用自己的版本替换了父类的 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:: 在原有实现的基础上进行扩展。

challenge icon

挑战

简单

我们来构建一个通知系统,演示子类如何通过方法重写完全替换或扩展父类的方法。

你将创建三个协同工作的文件,用来发送不同类型的通知,每种通知都有自己的行为:

  • 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. 带日志的通知

?>
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: PHP 在线编译器