PHP学习笔记(十二)

发布于:2025-07-01 ⋅ 阅读:(19) ⋅ 点赞:(0)

访问控制(可见性)

对属性或方法的访问控制(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 或未定义的属性。

  • 魔术方法不会改变实际的属性可见性,但会提供访问入口,常用于封装和懒加载。

抽象方法与可见性
  • 抽象方法只能声明为 publicprotected,不能是 private

  • 抽象方法必须在抽象类中定义,由子类实现具体功能。

常量的控制访问

自PHP 7.1后 , 类的常量可以定义为,public、private 或 protected ,没设置就默认public

其它对象的访问控制

同一个类的对象即使不是同一个实例也可以互相访问对方的private与protected成员。

接口中的方法可见性
  • 接口中的方法默认都是 public,不能声明为 protectedprivate

  • 实现接口时,方法必须保持为 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 中可以使用 publicprotectedprivate 来声明方法可见性。

  • 如果多个 Trait 有同名方法,需使用 insteadofas 解决冲突,且可改变方法可见性。

返回类型与内部类兼容

PHP 8.1前,大多数内部类或方法没有声明其返回类型,并且在继承它们是允许返回任何类型。

自PHP 8.1起 大多数内部方法开始“暂时”声明其返回类型,在这种情况下,方法的返回类型应该与继承的父级方法兼容,否则,将发出弃用通知。注意,没有指定返回声明也会视为签名不匹配,从而导致弃用通知。

反射 API 可突破可见性
  • PHP 的 ReflectionPropertyReflectionMethod 等允许在运行时读取和修改 privateprotected 成员。

  • 通过 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手册


网站公告

今日签到

点亮在社区的每一天
去签到