Which of the following is not the type of inheritance supported in php

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.

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.

class {
    public 
int $prop;
}
class 
extends {
    
// Illegal: read-write -> readonly
    
public readonly int $prop;
}
?>

Example #1 Inheritance Example

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'?>

Return Type Compatibility with Internal Classes

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

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

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

class MyDateTime extends DateTime
{
    
/**
     * @return DateTime|false
     */
    #[ReturnTypeWillChange]
    
public function modify(string $modifier) { return false; }
}
// No notice is triggered 
?>

jackdracona at msn dot com

12 years ago

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:

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?>

Mohammad Istanbouly

5 years ago

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

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

}

akashwebdev at gmail dot com

7 years ago

The Idea that multiple inheritence is not supported is correct but with tratits this can be reviewed.

for e.g.

trait  custom
{
     public function
hello()
     {
          echo
"hello";
     }
}

trait

custom2
{
       public function
hello()
       {
            echo
"hello2";
       }
}

class

inheritsCustom
{
        use
custom, custom2
       
{
             
custom2::hello insteadof custom;
        }
}
$obj = new inheritsCustom();
$obj->hello();
?>

strata_ranger at hotmail dot com

12 years ago

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:

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]
?>

niemans at pbsolo dot nl

2 years ago

Inheritance works at create time, i.e. using the keyword 'new'. Static properties confused my understanding, so in order tho show the effect of visibility to inherintence I've created a simple demo script along with some set and get magic:

class A {
private
$a   = 'private';
protected
$b = 'protected';
public
$c    = 'public';
static
$d    = 'static';
public function
__construct()
{
   
$this->e = 'constructed';
}
public function
__set($property, $value)
{
    echo
' set ' . $property . '=' . $value;
   
$this->$property=$value;
}
public function
__get($property)
{
    echo
' get ' . $property;
   
$this->$property = 'dynamic'// invokes __set() !!
   
return $this->$property;
}
}

class

B extends A
{
public function
constructMe()
{
   
$this->e = 'constructed2';
}
}

class

C extends B
{
public function
__construct()
{
   
parent::constructMe();
}
}

echo

" \n";
$a = new A();
$b = new B();
echo
" \n";
echo
' B:c='.$b->c;
echo
" \n";
echo
' B:d=' .$b->d;
echo
" \n";$c = new C();
echo
" \n";print_r($a);
print_r($b);
print_r($c);print_r(A::$d);
print_r(B::$d);
print_r(C::$d);

echo

'A class: ';
$R = new reflectionclass('A');
print_r($R->getdefaultproperties());
print_r($R->getstaticproperties());
echo
'B class: ';
$R = new reflectionclass('B');
print_r($R->getdefaultproperties());
print_r($R->getstaticproperties());?>

This outputs:

set e=constructed
B:c=public
get d set d=dynamic B:d=dynamic
set e=constructed2
A Object
(
    [a:A:private] => private
    [b:protected] => protected
    [c] => public
    [e] => constructed
)
B Object
(
    [a:A:private] => private
    [b:protected] => protected
    [c] => public
    [d] => dynamic
)
C Object
(
    [a:A:private] => private
    [b:protected] => protected
    [c] => public
    [e] => constructed2
)
staticstaticstaticA class: Array
(
    [d] => static
    [a] => private
    [b] => protected
    [c] => public
)
Array
(
    [d] => static
)
B class: Array
(
    [d] => static
    [b] => protected
    [c] => public
)
Array
(
    [d] => static
)

This shows how private variables ($a) are inherited, how static variables ($d) are inherited (by the class, not by the object) and that changing or adding variables in the parent ($e, $d) are not inherited by the child.

jarrod at squarecrow dot com

12 years ago

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........

abstract class Cheese
{
     
//can ONLY be inherited by another class
}

class

Cheddar extends Cheese
{
}
$dinner = new Cheese; //fatal error
$lunch = new Cheddar; //works!?>

Anonymous

3 years ago

PHP7 gives you a warning if you redeclare a function in a child class with different parameters. For example:

class foo {
     function print($text='') {
          print text;
     }
}

class bar extends foo {
      function print($text1='',$text2='') {
           print text1.text2
      }
}

will give a PHP Warning:  Declaration of bar::print($text1 = '', $text2 = '') should be compatible with foo::print($text= '').

Sam Tigall

3 years ago

Overriding a method which is called from base class works like this:

class Foo
{
    public function
printItem($string)
    {
        echo
'Foo: ' . $string;
    }

        public function

printPHP($string)
    {
       
$this->printItem($string);
    }
}

class

Bar extends Foo
{
    public function
printItem($string)
    {
        echo
'Bar: ' . $string ;
    }
}
$foo = new Foo();
$bar = new Bar();
$foo->printPHP('baz'); //Foo: baz
$bar->printPHP('baz'); //Bar: baz
?>

sibian0218 at gmail dot com

4 years ago

I've noticed one thing concerning inheritance...
When declaring an abstract class with a private method,
which is overridden by a sub-class, private takes precedence over public for child class...
(in the case you're redeclaring a method with a different signature in fact).

Hope this helps

nemanja

5 years ago

Even when autoloading (SPL) is used, class inheritance does not seem to work. Simply the PHP engine is unable to find parent (inherited) class. PHP 5.6 and 7.0 behave exactly same on this, which beats the purpose of autoloading.

And IMHO it's easy to fix as the autoloader is able to find all first level classes w/o problems, it just needs to follow same path recursively on parents too.

//Using default SPL autoloader, with namespaces mapping 1:1 to directory structure, with file names being all lowercase.
//This works with first level classes only, for inheritance it does NOT work, it cannot find parent classes.
spl_autoload_register();//This is ugly but working code if you want to be able to autoload parent classes too.
spl_autoload_register(function ($class){
    require_once
__DIR__ . '/' . strtolower(str_replace('\\', '/', $class) . '.php');
});

gino dot d at amail dot com

5 years ago

A simple trait to create multi inheritance in php

trait tExtend {
    private
$objectExtend = [];

    final public function

extend() {
        foreach (
$objects = func_get_args() as &$object) {
            if (
is_object($object) && !$object instanceOf self) {
               
$this->objectExtend[] = $object;

                                if (

is_callable([$object, 'syncExtend']))
                   
$object->syncExtend($this, $objects);
            }
        }
    }

    final public function

syncExtend(&$object = null, array $objects) {
        if (
is_object($object) && !$object instanceOf self && !in_array($object, $this->objectExtend))
           
$this->objectExtend[] = $object;

        foreach (

$objects as &$object)
            if (
is_object($object) && !$object instanceOf self && !in_array($object, $this->objectExtend))
               
$this->objectExtend[] = $object;

        return

$this;
    }

    final public function

__call($method, $args) {
        if (
method_exists($this, $method))
            return
$this->{$method}(... $args);
        else {
            foreach (
$this->objectExtend as $i => &$object) {
                if (
method_exists($object, $method))
                    return
$object->{$method}(... $args);
            }
        }

        throw new \

Exception('Call to undefined method ' . get_called_class() .  '::' . $method . '()');
    }

    final public function

__get($key) {
        if (
array_key_exists($key, $this))
            return
$this->{$key};

        foreach (

$this->objectExtend as &$object) {
            if (
array_key_exists($key, $object))
                return
$object->{$key};
        }
trigger_error('Undefined property: ' . get_called_class() . '::$' . $key, E_USER_NOTICE);
    }

    final public function

__isset($key) {
        if (
array_key_exists($key, $this))
            return
true;

        foreach (

$this->objectExtend as &$object) {
            if (
array_key_exists($key, $object))
                return
true;
        }

        return

false;
    }
}
/*************/class F {
    public
$relationship = 'Sister';
}

class

M {
    public
$relationship = 'Brother';
}

class

A extends M {
    use
tExtend;
}
class
B extends F {
    use
tExtend;

    function

getName() {
        return
'B';
    }
}
class
C extends F {
    use
tExtend;

    function

getName() {
        return
'C';
    }
}
class
D extends M {
    use
tExtend;
}

class

{
    use
tExtend;

    function

getParent() {
        return
'Z';
    }

    function

__construct() {
       
$this->extend(... func_get_args());
    }
}
$a = new A;
$b = new B;
$c = new C;
$d = new D;
$z = new Z($a, $b, $c, $d);$d->extend($a); // Change nothing
$a->varA = 'A';
$c->varA = 'C';

echo

$a->getParent(); // print Z
echo $a->getName(); // print B
echo $b->getName(); // print B
echo $c->getName(); // print C
echo $d->getName(); // print B
echo $z->getName(); // print B
echo $z->varA; // print A
echo $c->varA; // print C
?>

ghoucine at gmail dot com

8 years ago

For multiple single inheretance to work the order of class definition is very important if you're going up more than two levels in inheretence.

This won't work:

class A extends B {}

class

B extends C {}

class

C {}$A = new A;
?>
Running the code above will spit a fatal error (Fatal Error:Class 'B' not found)

A change in class definition order will fix this:

class A extends B {}

class

C {}

class

B extends C {}$A = new A;
?>

If you're goin up just one level in inhertance though there shouldn't be any problem. So this code works too:

class A extends B {}

class

{}$A = new A;?>

I have no explanation as to why this is the case though.

shaun at slickdesign dot com dot au

4 years ago

Similar to functions, unless they are in conditionals, it is possible to define classes anywhere within your script and they still generate instances.

It is also possible to define child classes before the parent class, however, this seems to act the same way as a conditional, meaning that you need to define these classes before they can be used.

Examples:

- Standard usage (A and B are always accessible)
class A {}
class
B extends A {}var_dump( class_exists( 'A' ), class_exists( 'B' ) );
// Outputs: bool(true) bool(true)
?>

- End of file declaration (A and B are still always accessible, even if you have a return or exit before it)
var_dump( class_exists( 'A' ), class_exists( 'B' ) );
// Outputs: bool(true) bool(true)die;
class
A {}
class
B extends A {}
?>

- Child before parent declaration (B is not accessible until it has been defined)
var_dump( class_exists( 'A' ), class_exists( 'B' ) );
// Outputs: bool(true) bool(false)class B extends A {}
var_dump( class_exists( 'B' ) );
// Outputs: bool(true)class A {}
?>

- Conditional definition (Same as child before parent example above)
var_dump( class_exists( 'A' ), class_exists( 'B' ) );
// Outputs: bool(true) bool(false)if ( ! class_exists( 'B' ) ) {
    class
B extends A {}
}
var_dump( class_exists( 'B' ) );
// Outputs: bool(true)class A {}

tim at web dot com

5 years ago

[Document:Main.php]
//
include("person.php");       
include(
"student.php");   
include(
"teacher.php");       
//-----Creating a object of the class "teacher"--------
$t1=new teacher();
$t1->name="Mustermann";
$t1->forename="Max";
$t1->email="";

echo

$t1->name.", ".$t1->forename.": ".$t1->email;
$t1->ID();//-----Creating a object of the class "student"--------
$s1=new student();
$s1->name="Kevin";
$s1->forename="Alpha";

echo

$s1->name."; ".$s1->forename;
$s1->ID();
?>

//-------------------------------------------------------------------------------------------
[Document:person.php]
class person
{
 
//Attribute
 
public $name;
  public
$forename;
}
?>

//-------------------------------------------------------------------------------------------
[Document:teacher.php]
class teacher extends person    /
{
 
//Attribute
 
public $email;
 
//Function
 
public function ID()
  {
    echo
"

I am a teacher

"

  }
}
?>

//-------------------------------------------------------------------------------------------
[Document:student.php]
class student extends Person
{
 
//Attribute
  //Functionen
 
public function ID()
  {
    echo
"

I am a student

"

  }
}
?>

clintonabco at gmail dot com

5 years ago

This page is not clear about the nature and specifics of Object Inheritance especially that you can only make the visibility of an inherited method or property weaker and not stronger within the subclass that is inheriting these from its parent class.

Example:

class Test1
{
    protected
$a_property = "This is a property";

        protected function

printProperty()
    {
        echo
$this->a_property;
    }
}

class

Test2 extends Test1
{
    private
$b_property = "This is another property";

        private function

printProperty()
    {
        echo
$this->b_property;
    }
}
$test2 = new Test2();
?>

This code produces a PHP Fatal error with message:

PHP Fatal error:  Access level to Test2::printProperty() must be protected (as in class Test1) or weaker

So if you inherit a protected method and you want redeclare it in your subclass then you can either declare its visibility as protected or public. If public is inherited then it stays public.

Here is the working version of the code snippet above:

class Test1
{
    protected
$a_property = "This is a property";

        protected function

printProperty()
    {
        echo
$this->a_property;
    }
}

class

Test2 extends Test1
{
    private
$b_property = "This is another property";

        public function

printProperty()
    {
        echo
$this->b_property;
    }
}
$test2 = new Test2();
$test2->printProperty();
?>

To iterate what the description on the page says, subclasses inherit all protected and public properties and methods.

php at sleep is the enemy dot co dot uk

12 years ago

Here's fun, an attempt to make some degree of multiple inheritance work in PHP using mixins. It's not particularly pretty, doesn't support method visibility modifiers and, if put to any meaningful purpose, could well make your call stack balloon to Ruby-on-Rails-esque proportions, but it does work.

abstract class Mix {

        protected

$_mixMap = array();

        public function

__construct(){$this->_mixMap = $this->collectMixins($this);
    }

        public function

__call($method, $args){// doesn't pass scope
        //return call_user_func_array(array($className, $method), $args);

                // Error: Given object is not an instance of the class this method was declared in
        //$method = new ReflectionMethod($className, $method);
        //return $method->invokeArgs($this, $args);

$payload = $this->buildMixinPayload($this->_mixMap, $method, $args);
        if(!
$payload) throw new Exception('Method ' . $method . ' not found');

                list(

$mixinMethod, list($method, $args)) = $payload;

                return

$this->$mixinMethod($method, $args);

            }

        protected function

collectMixins($class){

                static

$found = array();
        static
$branch = array();

                if(empty(

$branch)) $branch[] = get_class($this);
       
$mixins = array();

                foreach(

array_reverse(get_class_methods($class)) as $method){
            if(
preg_match('/^mixin(\w+)$/', $method, $matches)){$className = $matches[1];

                                if(

in_array($className, $branch))
                    throw new
Exception('Circular reference detected ' . implode(' > ', $branch) . ' > ' . $className);

                                    if(!

in_array($className, $found)){

                                    if(!

class_exists($className)) throw new Exception('Class ' . $className . ' not found');// populate props from mixin class
                   
foreach(get_class_vars($className) as $key => $value){       
                        if(!
property_exists($this, $key)) $this->$key = $value;
                    }
$found[] = $branch[] = $className;               
                   
$mixins[$className] = $this->collectMixins($className);
                }
$branch = array(get_class($this));
            }
        }

                return

$mixins;
    }

        protected function

buildMixinPayload($mixins, $method, $args){

                foreach(

$mixins as $className => $parents){$mixinMethod = 'mixin' . $className;

                        if(

method_exists($className, $method)) return array($mixinMethod, array($method, $args));

                        if(!empty(

$parents) && $return = $this->buildMixinPayload($parents, $method, $args)){
                return array(
$mixinMethod, $return);
            }
        }

                return

false;
    }

    }

?>

msg2maciej at aol dot com

11 years ago

PHP supports single class inheritance. My bare idea on accessing protected methods with power of abstracts and sort of "multi-class inheritance SIMULATION":

error_reporting(E_ALL);

abstract class

Base {
    abstract protected function
__construct ();
    abstract protected function
hello_left ();
    abstract protected function
hello_right ();
}

abstract class

NotImplemented_Left extends Base {
protected function
hello_right () {
echo
'well, wont see that'; }}

abstract class

NotImplemented_Right extends Base {
protected function
hello_left () {
echo
'well, wont see that'; }}

class

Left extends NotImplemented_Left {
protected function
__construct () {        # limited visibility, no access from "outside"
echo __CLASS__.'::protected __construct'. "\n"; }
protected function
hello_left () {        # limited visibility, no access from "outside"
echo 'protected hello_left in ' . __CLASS__ . "\n"; }}

class

Right extends NotImplemented_Right {
protected function
__construct () {        # limited visibility, no access from "outside"
echo __CLASS__.'::protected __construct'. "\n"; }
protected function
hello_right () {        # limited visibility, no access from "outside"
echo 'protected hello_right in ' . __CLASS__ . "\n"; }
protected function
hello_left () {
echo
"wont see that, and easy to get rid of it from here\n"; }}

class

Center extends Base {
private
$left;
private
$right;
public function
__construct () {
echo
'welcome in ' . __CLASS__ . "\n";
echo
'Center::'; $this->left = new Left;
echo
'Center::'; $this->right = new Right;
echo
" oh and\n";
$this->hello_left();
$this->hello_right();
}
public function
hello_left () {            # calling class Left
echo __CLASS__.'::'; $this->left->hello_left(); }
public function
hello_right () {        # calling class Right
echo __CLASS__.'::'; $this->right->hello_right(); }
}
$c = new Center;
?>

Produces:

welcome in Center
Center::Left::protected __construct
Center::Right::protected __construct
oh and
Center::protected hello_left in Left
Center::protected hello_right in Right

Which type of inheritance is not supported by PHP?

PHP doesn't support multiple inheritance but by using Interfaces in PHP or using Traits in PHP instead of classes, we can implement it. Traits (Using Class along with Traits): The trait is a type of class which enables multiple inheritance.

Which type of inheritance is supported by PHP?

It supports the concept of hierarchical classification. Inheritance has three types, single, multiple and multilevel Inheritance. PHP supports only single inheritance, where only one class can be derived from single parent class. We can simulate multiple inheritance by using interfaces.

Which type of inheritance is not supported?

Consider a case where class B extends class A and Class C and both class A and C have the same method display(). Now java compiler cannot decide, which display method it should inherit. To prevent such situation, multiple inheritances is not allowed in java.

Why is multiple inheritance not supported in PHP?

PHP programming language doesn't even support the multiple inheritance/inheritances. PHP supports multiple inheritances only by using interfaces or Traits in PHP instead of classes so that we can implement it. Traits are a type of class that enables multiple case classes, objects, classes, and traits.