一、概念
继承是面向对象编程中一个非常重要的特性,在 PHP 的对象模型中,继承关系可以用于扩展已有类的功能,从而减少代码的重复和提高代码的可维护性。子类可以通过 extends 关键字来继承父类的属性和方法,会自动继承父类的 public 和 protected 属性和方法,但不会继承私有属性和方法。如果子类需要访问父类的私有属性或方法,可以通过在父类中定义公有或受保护的方法来实现。
当子类继承了父类的方法时,这些方法都会保留其原有的功能,除非子类覆盖了这些方法。子类可以通过重载(即覆盖)父类的方法来实现自己的功能,从而实现对父类的扩展和重用。同时,子类也可以通过调用 parent:: 方法名 来调用父类中被覆盖的方法,从而实现对父类方法的扩展。
通过继承,PHP 中的类与类、对象与对象之间形成了一种层次结构,从而实现了代码的分层和组织。这种层次结构可以让我们更好地管理和维护代码,同时也提高了代码的可重用性和可扩展性。另外,继承有助于功能的设计和抽象,在实现类似的对象、增加新功能时,无须重复编写这些公用的功能。
子类无法访问父类的私有方法。 因此,子类无需考虑正常的继承规则而重新实现私有方法。 然而,在 PHP 8.0.0 之前, 和 的限制会应用于 private 方法。 从 PHP 8.0.0 开始,仅 的构造器是唯一受限的 private 方法; 想要“禁用”构造器,我们通常用静态工厂方法作为代替。 finalstaticprivate final
注意:
- 除非使用了自动加载,否则一个类必须在使用之前被定义。 如果一个类扩展了另一个,则父类必须在子类之前被声明。 此规则适用于类继承其它类与接口。
- 不允许用只读属性重写读写属性,反之亦然。
<?php class A { public int $prop; } class B extends A { // Illegal: read-write -> readonly public readonly int $prop; } ?>
二、继承示例
<?php class Foo { public function printItem($string) { echo 'Foo: ' . $string . PHP_EOL; } public function printPHP() { echo 'PHP is great.' . PHP_EOL; } } class Bar extends Foo { public function printItem($string) { echo 'Bar: ' . $string . PHP_EOL; } } $foo = new Foo(); $bar = new Bar(); $foo->printItem('baz'); // 输出: 'Foo: baz' $foo->printPHP(); // 输出: 'PHP is great' $bar->printItem('baz'); // 输出: 'Bar: baz' $bar->printPHP(); // 输出: 'PHP is great' ?>
三、返回类型与内部类兼容性
在 PHP 8.1 之前,大多数内部类或方法都没有声明它们的返回类型, 并且在扩展时允许任何返回类型。从 PHP 8.1.0 开始,大多数内部方法开始“暂时”声明它们的返回类型, 在这种情况下,方法的返回类型应与要扩展的父项兼容,否则将发出弃用通知。
如果因为 PHP 跨版本兼容性问题而无法为重写方法声明返回类型, 可以添加 ReturnTypeWillChange 属性来使弃用通知静音。
重写方法不声明任何返回类型示例:
<?php class MyDateTime extends DateTime { public function modify(string $modifier) { return false; } } // "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0 ?>
重写方法声明了错误的返回类型示例:
<?php class MyDateTime extends DateTime { public function modify(string $modifier): ?DateTime { return null; } } // "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0 ?>
重写方法在没有弃用通知的情况下声明错误的返回类型示例:
<?php class MyDateTime extends DateTime { /** * @return DateTime|false */ #[\ReturnTypeWillChange] public function modify(string $modifier) { return false; } } // No notice is triggered ?>