继承已为大家所熟知的一个程序设计特性,PHP 的对象模型也使用了继承。继承将会影响到类与类,对象与对象之间的关系。
比如,当扩展一个类,子类就会继承父类所有 public 和 protected 的方法,属性和常量。除非子类覆盖了父类的方法,被继承的方法都会保留其原有功能。
继承有助于功能的设计和抽象,在实现类似的对象、增加新功能时,无须重复编写这些公用的功能。
子类无法访问父类的私有方法。因此,子类无需考虑正常的继承规则而重新实现私有方法。
然而,在 PHP 8.0.0 之前, final
和 static
的限制会应用于 private 方法。
从 PHP 8.0.0 开始,仅 private final
的构造器是唯一受限的 private 方法;
想要“禁用”构造器,我们通常用静态工厂方法作为代替。
方法,属性和常量的 可见性
可以放宽,例如 protected
方法可以标记为 public
,
但不能增加限制,例如标记 public
属性为 private
。
注意:
除非使用了自动加载,否则一个类必须在使用之前被定义。如果一个类扩展了另一个,则父类必须在子类之前被声明。此规则适用于类继承其它类与接口。
注意:
It is not allowed to override a read-write property with a readonly property or vice versa.
<?php
class A {
public int $prop;
}
class B extends A {
// Illegal: read-write -> readonly
public readonly int $prop;
}
?>
示例 #1 继承示例
<?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'
?>
Prior to PHP 8.1, most internal classes or methods didn't declare their return types, and any return type was allowed when extending them.
As of PHP 8.1.0, most internal methods started to "tentatively" declare their return type, in that case the return type of methods should be compatible with the parent being extended; otherwise, a deprecation notice is emitted. Note that lack of an explicit return declaration is also considered a signature mismatch, and thus results in the deprecation notice.
If the return type cannot be declared for an overriding method due to PHP cross-version compatibility concerns,
a #[ReturnTypeWillChange]
attribute can be added to silence the deprecation notice.
示例 #2 The overriding method does not declare any return type
<?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
?>
示例 #3 The overriding method declares a wrong return type
<?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
?>
示例 #4 The overriding method declares a wrong return type without a deprecation notice
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// No notice is triggered
?>