深入了解访问修饰符
本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 39 课,共 91 课。
现在你已经了解了三种访问修饰符,接下来我们来看看它们在继承场景中的行为。关键是,子类可以访问 protected 成员,而 private 成员仍然对它们隐藏,即使是对子类也一样。
<?php
class Vehicle {
public $brand;
protected $engineType;
private $serialNumber;
public function __construct($brand, $engine, $serial) {
$this->brand = $brand;
$this->engineType = $engine;
$this->serialNumber = $serial;
}
private function getSerial() {
return $this->serialNumber;
}
protected function getEngineInfo() {
return $this->engineType;
}
}
class Car extends Vehicle {
public function getDetails() {
return $this->brand . " - " . $this->getEngineInfo();
// 访问 $this->serialNumber 会报错,因为它是私有属性!
// 调用 $this->getSerial() 也会失败,因为它是私有方法!
}
}
$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();
输出:
Toyota - V6Car 类可以访问 $brand(public),也可以调用 getEngineInfo()(protected),但无法访问 $serialNumber 或 getSerial(),因为它们是 Vehicle 的私有内容。这种区别让你可以与子类共享某些内部细节,同时将其他内容完全隐藏起来。
要点:当子类需要访问内部数据或方法时,使用 protected;当某些实现细节连子类也不应访问时,使用 private。
挑战
简单我们来构建一个设备管理系统,看看访问修饰符在继承中的表现。你将创建一个基础 Device 类,其中的属性具有不同的可见性级别,然后通过扩展它来创建 Smartphone 类,展示子类可以和不可以访问哪些成员。
你将把代码组织在三个文件中:
Device.php:创建一个Device类,用来表示数据敏感级别不同的电子设备。包含:- 一个
public属性$brand,用于存储制造商名称 - 一个
protected属性$modelNumber,用于内部标识 - 一个
private属性$manufacturingCode,用于存储仅供工厂使用的数据
private方法getManufacturingCode(),用于返回制造代码。添加一个public方法getModelInfo(),用于返回"Model: [modelNumber]"。最后,添加一个public方法getFullCode(),用于返回"[brand]-[manufacturingCode]"。这展示了类本身如何访问自己的私有成员。- 一个
Smartphone.php:创建一个继承自Device的Smartphone类。引入 Device 文件。构造函数应接收品牌、modelNumber、manufacturingCode 和操作系统名称。用前三个值调用父类构造函数,然后将操作系统存储在一个私有属性中。添加一个公共方法getDeviceDetails(),用于返回"[brand] [modelNumber] running [os]"。注意,你可以直接访问公共属性$brand和受保护属性$modelNumber,但不能直接访问私有属性$manufacturingCode:你需要改用继承而来的公共方法getFullCode()。main.php:引入 Smartphone 文件。你将收到四个输入:品牌名称、型号、制造代码和操作系统。用这些值创建一个Smartphone实例。打印三行:- 调用
getDeviceDetails()的结果 - 调用继承而来的
getModelInfo()方法的结果 - 调用继承而来的
getFullCode()方法的结果
- 调用
这个挑战重点展示了两者的区别:你的 Smartphone 类可以自由使用从 Device 继承而来的受保护属性 $modelNumber,但私有属性 $manufacturingCode 和方法 getManufacturingCode() 完全不可见:只能通过 Device 选择公开的公共接口访问。
亲手试试
<?php
require_once 'Smartphone.php';
// 读取输入
$brand = trim(fgets(STDIN));
$modelNumber = trim(fgets(STDIN));
$manufacturingCode = trim(fgets(STDIN));
$os = trim(fgets(STDIN));
// TODO:用输入的值创建一个 Smartphone 实例
// TODO:打印 getDeviceDetails() 的结果
// TODO:打印继承的 getModelInfo() 方法的结果
// TODO:打印继承的 getFullCode() 方法的结果
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: PHP 在线编译器