PHP protected 关键字
最后修改于 2025 年 4 月 16 日
PHP protected
关键字是面向对象编程中使用的可见性修饰符。它控制对类成员(属性和方法)的访问。受保护的成员可以在类及其子类中访问。
基本定义
protected
关键字使类成员对类本身及其扩展的任何类都可用。这比 public 具有更严格的限制,但比 private 可见性限制更少。
受保护的成员无法从类层次结构外部访问。它们是为子类可能需要访问的内部类实现细节而设计的。
语法:protected $property;
或 protected function method() {}
。protected 修饰符可以应用于属性和方法。
基本受保护属性
此示例演示了父类中的一个简单受保护属性。
<?php declare(strict_types=1); class Vehicle { protected $model; public function setModel(string $model): void { $this->model = $model; } } class Car extends Vehicle { public function getModel(): string { return $this->model; } } $car = new Car(); $car->setModel("Toyota"); echo $car->getModel();
$model
属性在 Vehicle 类中受保护。Car 类可以访问它,因为它继承了 Vehicle。该属性无法直接从这些类外部访问。
受保护的方法继承
此示例显示了如何在继承中使用受保护的方法。
<?php declare(strict_types=1); class Animal { protected function makeSound(): string { return "Some generic animal sound"; } } class Dog extends Animal { public function bark(): string { return $this->makeSound() . " - Woof!"; } } $dog = new Dog(); echo $dog->bark();
makeSound
方法在 Animal 中受保护。Dog 类可以在内部调用此方法。外部代码无法直接调用 makeSound()。这强制了封装,同时允许继承。
从子类访问受保护成员
此示例演示了从子类访问受保护成员。
<?php declare(strict_types=1); class BankAccount { protected $balance = 0; protected function deposit(int $amount): void { $this->balance += $amount; } } class SavingsAccount extends BankAccount { public function addMoney(int $amount): void { $this->deposit($amount); echo "New balance: " . $this->balance; } } $account = new SavingsAccount(); $account->addMoney(100);
SavingsAccount 可以从其父类访问受保护的属性 $balance
和方法 deposit
。公共的 addMoney() 方法提供了对这些受保护成员的受控访问。
受保护的构造函数
此示例显示了在单例模式中使用受保护的构造函数。
<?php declare(strict_types=1); class Logger { protected function __construct() { echo "Logger initialized"; } public static function getInstance(): self { static $instance = null; if (null === $instance) { $instance = new static(); } return $instance; } } $logger = Logger::getInstance();
构造函数受到保护以防止直接实例化。静态的 getInstance() 方法控制对象创建。这是一种常见的单例类模式。
重写受保护的方法
此示例演示了在子类中重写受保护的方法。
<?php declare(strict_types=1); class Shape { protected function calculateArea(): float { return 0; } public function getArea(): float { return $this->calculateArea(); } } class Circle extends Shape { protected float $radius; public function __construct(float $radius) { $this->radius = $radius; } protected function calculateArea(): float { return pi() * $this->radius * $this->radius; } } $circle = new Circle(5); echo $circle->getArea();
Circle 类重写了 Shape 类的受保护的 calculateArea
方法。公共的 getArea() 方法提供对计算的访问。这显示了具有受保护方法的多态行为。
Trait 中的受保护属性
此示例显示了在 traits 中使用的受保护属性。
<?php declare(strict_types=1); trait Loggable { protected $logMessages = []; protected function addLog(string $message): void { $this->logMessages[] = $message; } public function getLogs(): array { return $this->logMessages; } } class User { use Loggable; public function login(): void { $this->addLog("User logged in"); } } $user = new User(); $user->login(); print_r($user->getLogs());
该 trait 定义了受保护的属性 $logMessages
和方法 addLog
。使用该 trait 的 User 类可以访问这些受保护的成员。 Traits 通过可见性控制提供水平代码重用。
Protected vs Private
此示例比较了 protected 和 private 可见性。
<?php declare(strict_types=1); class ParentClass { private $privateVar = "private"; protected $protectedVar = "protected"; } class ChildClass extends ParentClass { public function showProtected(): string { return $this->protectedVar; } public function showPrivate(): string { return $this->privateVar; // This will cause an error } } $child = new ChildClass(); echo $child->showProtected(); // echo $child->showPrivate(); // Would cause fatal error
子类可以访问受保护的属性,但不能访问私有属性。这演示了 protected 和 private 可见性之间的关键区别。protected 允许继承访问,而 private 仅限于定义类。
最佳实践
- 封装: 对子类需要实现的细节使用 protected。
- 文档: 为继承类清晰地记录受保护的成员。
- 访问控制: 对于内部类 API,优先使用 protected 而不是 public。
- 测试: 通过公共接口或反射测试受保护的方法。
- 设计: 考虑使用 protected abstract 方法进行模板方法。
来源
本教程通过实际示例介绍了 PHP protected 关键字,展示了各种面向对象场景中的受保护属性和方法。
作者
列出 所有 PHP 教程。