抽象类
本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 25 课,共 91 课。
抽象类是不能直接实例化的类。它为其他类提供蓝图,并定义子类必须实现的方法。你可以使用 abstract 关键字创建抽象类。
<?php
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
abstract public function calculateArea();
public function getColor() {
return $this->color;
}
}
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($color, $width, $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function calculateArea() {
return $this->width * $this->height;
}
}
$rect = new Rectangle("blue", 5, 3);
echo $rect->calculateArea();
输出:
15Shape 类声明了抽象方法 calculateArea(),但没有提供实现。任何继承 Shape 的类都必须实现这个方法。注意,抽象类也可以包含普通方法,例如 getColor(),子类可以直接继承这些方法。
抽象方法定义了子类必须做什么,但不定义如何做。这样可以确保所有形状都有 calculateArea() 方法,同时允许每种形状用不同的方式计算面积。
要点:抽象类将继承结构与强制要求结合起来。当你想在相关类之间共享代码,同时确保每个子类都实现某些方法时,可以使用抽象类。
挑战
简单我们来构建一个媒体播放器系统,展示抽象类如何规定契约,同时允许不同的媒体类型实现各自的播放行为。
你将把代码分到三个文件中:
Media.php:定义一个抽象Media类,作为所有媒体类型的蓝图。它应包含一个受保护的$title属性,以及一个用于接收并设置标题的构造函数。添加一个名为play()的抽象方法,子类必须实现它。再添加一个常规方法getTitle(),用于返回标题。所有子类都会继承这个具体方法。Song.php:定义一个继承Media的Song类。在文件顶部引入 Media 文件。这个类会添加一个$artist属性。构造函数应接收标题和艺术家:使用parent::__construct()设置标题,然后自行设置艺术家。实现必需的play()方法,使其返回"Playing song: [title] by [artist]"。Podcast.php:定义一个继承Media的Podcast类。在文件顶部引入 Media 文件。这个类会添加一个$episode属性(整数)。构造函数应接收标题和集数:使用parent::__construct()设置标题,然后设置集数。实现必需的play()方法,使其返回"Playing podcast: [title] - Episode [episode]"。
在 main.php 中,引入 Song 和 Podcast 文件。你会收到 4 个输入:歌曲标题、艺术家姓名、播客标题和集数(输入为字符串,需要转换为整数)。使用这些值创建一个 Song 对象和一个 Podcast 对象。先打印对歌曲调用 play() 的结果,再打印对播客调用 play() 的结果,每个结果各占一行。
这个挑战展示了抽象类如何定义契约:每种媒体类型都必须有一个 play() 方法,但每种类型的实现方式都不同。抽象 Media 类不能直接实例化,它的作用只是为子类提供结构和共享功能。
亲手试试
<?php
require_once 'Song.php';
require_once 'Podcast.php';
// 读取输入
$songTitle = trim(fgets(STDIN));
$artistName = trim(fgets(STDIN));
$podcastTitle = trim(fgets(STDIN));
$episodeNumber = intval(trim(fgets(STDIN)));
// TODO: 使用 songTitle 和 artistName 创建一个 Song 对象
// TODO: 使用 podcastTitle 和 episodeNumber 创建一个 Podcast 对象
// TODO: 输出对歌曲调用 play() 的结果
// TODO: 输出对播客调用 play() 的结果
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: PHP 在线编译器