PHP学习笔记(十二)
访问控制(可见性)
对属性或方法的访问控制(PHP 7.1后支持常量),是通过在前面添加关键字public (公有)、protected 、 private 来实现。公有的任意可见,受保护的可被自身及其子类和父类访问,私有的只能被其定义所在的类访问
属性的访问控制
类属性可以定义为public,private或者protected 。在没有任何访问控制关键字的情况下,属性声明为public
不对称属性可见性
从PHP 8.4开始,属性也可以设置不对称的可见性,读取(get)和写入(set)可以有不同的范围,准确的说可以单独指定set可见性,只要它不比默认可见性更宽。
当一个类继承另一个类时,子类可以重新定义任何不是final的属性。这样做时,可以扩大主要可见性或set可见性,只要新的可见性和父类相同或者更宽,需要注意的是,若一个private属性被重写,它实际上并没有改变父类的属性,而是创建了一个具有不同内部名称的新属性。
方法的访问控制
类中的方法可以被定义为public、private、protected。如果没设置默认为public
魔术方法与可见性
-
通过实现
__get()
、__set()
等魔术方法,可以动态访问private
或未定义的属性。 -
魔术方法不会改变实际的属性可见性,但会提供访问入口,常用于封装和懒加载。
抽象方法与可见性
-
抽象方法只能声明为
public
或protected
,不能是private
。 -
抽象方法必须在抽象类中定义,由子类实现具体功能。
常量的控制访问
自PHP 7.1后 , 类的常量可以定义为,public、private 或 protected ,没设置就默认public
其它对象的访问控制
同一个类的对象即使不是同一个实例也可以互相访问对方的private与protected成员。
接口中的方法可见性
-
接口中的方法默认都是
public
,不能声明为protected
或private
。 -
实现接口时,方法必须保持为
public
,否则会报错。
对象继承
PHP的对象模型使用了继承,继承可以影响到类与类,对象与对象之间的关系。
比如,当扩展一个类,子类就会继承父类所有public和protected的方法,属性和常量。除非子类覆盖了父类的方法,被继承的方法都会保留其原有功能。
继承有助于功能的设计和抽象,在实现类似的对象、增加新功能时,无须重复编写这些公用的功能
子类无法访问父类的私有方法。因此,子类无需考虑正常的继承规则而重新实现私有方法。然而,在PHP 8.0前,final和static 的限制会应用于private方法。自PHP 8.0起,仅private final 的构造器是唯一受限的private方法;想要“禁用”构造器,通常使用静态工厂方法作为代替。
方法,属性和常量的可见性可以放宽,例如protected方法可以标记为public,但不能增加限制,例如标记public属性为private。
使用 final
限制继承或重写
-
使用
final
可以防止某个方法被子类覆盖,或防止整个类被继承。 -
final
不改变可见性,但会影响继承层级的可扩展性。 -
从 PHP 8.0 起,
private
方法(除构造器外)不会受final
约束。
Trait(特征)与可见性
-
Trait 可用于多个类共享属性或方法。
-
Trait 中可以使用
public
、protected
、private
来声明方法可见性。 -
如果多个 Trait 有同名方法,需使用
insteadof
或as
解决冲突,且可改变方法可见性。
返回类型与内部类兼容
PHP 8.1前,大多数内部类或方法没有声明其返回类型,并且在继承它们是允许返回任何类型。
自PHP 8.1起 大多数内部方法开始“暂时”声明其返回类型,在这种情况下,方法的返回类型应该与继承的父级方法兼容,否则,将发出弃用通知。注意,没有指定返回声明也会视为签名不匹配,从而导致弃用通知。
反射 API 可突破可见性
-
PHP 的
ReflectionProperty
、ReflectionMethod
等允许在运行时读取和修改private
或protected
成员。 -
通过
setAccessible(true)
可访问原本不可见的属性或方法,适用于单元测试或框架内部。
封装示例(Best Practice)
展示如何组合 private + getter/setter + readonly
class Product {private float $price;public function __construct(float $price) {$this->price = $price;}public function getPrice(): float {return $this->price;}protected function setPrice(float $price): void {$this->price = $price;}
}
参考资料
PHP手册