Inheritance is a well-established programming principle, and PHP makes use
of this principle in its object model. This principle will affect the way
many classes and objects relate to one another.
For example, when extending a class, the subclass inherits all of the
public and protected methods, properties and constants from the parent class.
Unless a class overrides
those methods, they will retain their original functionality.
This is useful for defining and abstracting functionality, and permits the
implementation of additional functionality in similar objects without the
need to reimplement all of the shared functionality.
Private methods of a parent class are not accessible to a child class. As a result,
child classes may reimplement a private method themselves without regard for normal
inheritance rules. Prior to PHP 8.0.0, however, final and static
restrictions were applied to private methods. As of PHP 8.0.0, the only private method
restriction that is enforced is private final constructors, as that
is a common way to "disable" the constructor when using static factory methods instead.
The visibility
of methods, properties and constants can be relaxed, e.g. a
protected method can be marked as
public, but they cannot be restricted, e.g.
marking a public property as private.
An exception are constructors, whose visibility can be restricted, e.g.
a public constructor can be marked as private
in a child class.
Note:
Unless autoloading is used, the classes must be defined before they are
used. If a class extends another, then the parent class must be declared
before the child class structure. This rule applies to classes that inherit
other classes and interfaces.
Note:
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; } ?>
Example #1 Inheritance Example
<?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'); // Output: 'Foo: baz' $foo->printPHP(); // Output: 'PHP is great' $bar->printItem('baz'); // Output: 'Bar: baz' $bar->printPHP(); // Output: '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.
Example #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 ?>
Example #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 ?>
Example #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; } }
Here is some clarification about PHP inheritance – there is a lot of bad information on the net. PHP does support Multi-level inheritance. (I tested it using version 5.2.9). It does not support multiple inheritance.
This means that you cannot have one class extend 2 other classes (see the extends keyword). However, you can have one class extend another, which extends another, and so on.
Example:
<?php class A { // more code here }
class B extends A { // more code here }
class C extends B { // more code here }
$someObj = new A(); // no problems $someOtherObj = new B(); // no problems $lastObj = new C(); // still no problems
I think the best way for beginners to understand inheritance is through a real example so here is a simple example I can gave to you
<?php
class Person { public $name; protected $age; private $phone;
public function talk(){ //Do stuff here }
protected function walk(){ //Do stuff here }
private function swim(){ //Do stuff here } }
class Tom extends Person { /*Since Tom class extends Person class this means that class Tom is a child class and class person is the parent class and child class will inherit all public and protected members(properties and methods) from the parent class*/
/*So class Tom will have these properties and methods*/
//public $name; //protected $age; //public function talk(){} //protected function walk(){}
//but it will not inherit the private members //this is all what Object inheritance means }
You can force a class to be strictly an inheritable class by using the "abstract" keyword. When you define a class with abstract, any attempt to instantiate a separate instance of it will result in a fatal error. This is useful for situations like a base class where it would be inherited by multiple child classes yet you want to restrict the ability to instantiate it by itself.
Example........
<?php
abstract class Cheese { //can ONLY be inherited by another class }
class Cheddar extends Cheese { }
$dinner = new Cheese; //fatal error $lunch = new Cheddar; //works!
I was recently extending a PEAR class when I encountered a situation where I wanted to call a constructor two levels up the class hierarchy, ignoring the immediate parent. In such a case, you need to explicitly reference the class name using the :: operator.
Fortunately, just like using the 'parent' keyword PHP correctly recognizes that you are calling the function from a protected context inside the object's class hierarchy.
E.g:
<?php class foo { public function something() { echo __CLASS__; // foo var_dump($this); } }
class foo_bar extends foo { public function something() { echo __CLASS__; // foo_bar var_dump($this); } }
class foo_bar_baz extends foo_bar { public function something() { echo __CLASS__; // foo_bar_baz var_dump($this); }
public function call() { echo self::something(); // self echo parent::something(); // parent echo foo::something(); // grandparent } }
error_reporting(-1);
$obj = new foo_bar_baz(); $obj->call();
// Output similar to: // foo_bar_baz // object(foo_bar_baz)[1] // foo_bar // object(foo_bar_baz)[1] // foo // object(foo_bar_baz)[1]