Наследование

Наследование — это хорошо зарекомендовавший себя принцип программирования. PHP использует этот принцип в своей объектной модели. Этот принцип будет распространяться на то, каким образом множество классов и объектов относятся друг к другу.

Например, когда вы расширяете класс, дочерний класс наследует все публичные и защищенные методы из родительского класса. До тех пор пока не будут эти методы переопределены, они будут сохранять свою исходную функциональность.

Это полезно для определения и абстрагирования функциональности и позволяет реализовать дополнительную функциональность в похожих объектах без необходимости реализовывать всю общую функциональность.

Замечание:

Пока не используется автозагрузка, классы должны быть объявлены до того, как их будут использовать. Если класс расширяет другой, то родительский класс должен быть объявлен до наследующего класса. Это правило применяется к классам, которые наследуют другие классы или интерфейсы.

Пример #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'); // Output: 'Foo: baz'
$foo->printPHP();       // Output: 'PHP is great' 
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP();       // Output: 'PHP is great'

?>

Коментарии

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!

?>
2009-10-27 08:01:45
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
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.

<?php
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;
    }
   
}
?>
2010-04-07 05:36:31
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
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 {
       
// more code here
}
 
class 
extends {
       
// more code here
}
 
class 
extends {
       
// more code here
}
 
 
$someObj = new A();  // no problems
$someOtherObj = new B(); // no problems
$lastObj = new C(); // still no problems
 
?>
2010-04-14 23:53:15
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
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]

?>
2010-09-19 12:37:58
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
Автор:
Model for Mixins pattern:

<?php
interface IMixinsCaller
{
    public function 
__mixin_get_property($property);

    public function 
__mixin_set_property($property$value);

    public function 
__mixin_call($method$value);
}

abstract class 
MixinsCaller implements IMixinsCaller
{
    protected 
$mixins = array();

    public function 
__call($name$arguments)
    {
        if (!empty(
$this->mixins))
        {
            foreach (
$this->mixins as $mixin)
            {
                if (
method_exists($mixin$name))
                {
                    return 
call_user_func_array(array($mixin$name), $arguments);
                }
            }
        }
       
trigger_error('Non-existent method was called in class '.__CLASS__.': '.$nameE_USER_WARNING);
    }

    public function 
__mixin_get_property($property)
    {
        if (
property_exists($this$property))
        {
            return 
$this->$property;
        }
       
trigger_error('Non-existent property was get in class '.__CLASS__.': '.$propertyE_USER_WARNING);
    }

    public function 
__mixin_set_property($property$value)
    {
        if (
property_exists($this$property))
        {
            return 
$this->$property $value;
        }
       
trigger_error('Non-existent property was set in class '.__CLASS__.': '.$propertyE_USER_WARNING);
    }

    public function 
__mixin_call($method$value)
    {
        if (
method_exists($this$method))
        {
            return 
call_user_func_array(array($this$method), $value);
        }
       
trigger_error('Non-existent method was called in class '.__CLASS__.': '.$methodE_USER_WARNING);
    }

    public function 
AddMixin($mixin)
    {
       
$this->mixins[] = $mixin;
    }
}

abstract class 
Mixin
{
   
/** @var IMixinsCaller $parent_object */
   
private $parent_object;

    public function 
__construct(IMixinsCaller $parent_object)
    {
       
$this->parent_object $parent_object;
    }

    public function 
__get($property)
    {
        return 
$this->parent_object->__mixin_get_property($property);
    }

    public function 
__set($property$value)
    {
        return 
$this->parent_object->__mixin_set_property($property$value);
    }

    public function 
__call($method$value)
    {
        return 
$this->parent_object->__mixin_call($method$value);
    }
}
?>
2010-11-14 17:24:19
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
PHP supports single class inheritance. My bare idea on accessing protected methods with power of abstracts and sort of "multi-class inheritance SIMULATION":

<?php
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
2011-01-28 18:08:45
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
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:

<?php

class extends {}

class 
extends {}

class 
{}

$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:

<?php

class extends {}

class 
{}

class 
extends {}

$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:

<?php

class extends {}

class 
{}

$A = new A;

?>

I have no explanation as to why this is the case though.
2014-08-26 23:48:22
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
The Idea that multiple inheritence is not supported is correct but with tratits this can be reviewed.

for e.g.
 
<?php
trait  custom
{
     public function 
hello()
     {
          echo 
"hello";
     }
}

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

class 
inheritsCustom
{
        use 
customcustom2
       
{
             
custom2::hello insteadof custom;
        }
}

$obj = new inheritsCustom();
$obj->hello();
?>
2015-07-01 08:59:16
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
A simple trait to create multi inheritance in php

<?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() . '::$' $keyE_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 {
    public 
$relationship 'Sister';
}

class 
{
    public 
$relationship 'Brother';
}

class 
extends {
    use 
tExtend;
}
class 
extends {
    use 
tExtend;

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

    function 
getName() {
        return 
'C';
    }
}
class 
extends {
    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
?>
2017-03-15 19:36:14
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
Автор:
[Document:Main.php]
<?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="max@mustermann.com";

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]
<?php
class person
{
 
//Attribute
 
public $name;
  public 
$forename;
}
?>

//-------------------------------------------------------------------------------------------
[Document:teacher.php]
<?php
class teacher extends person    /
{
 
//Attribute
 
public $email;
 
//Function
 
public function ID()
  {
    echo 
"<p>I am a teacher</p>"
  }
}
?>

//-------------------------------------------------------------------------------------------
[Document:student.php]
<?php
class student extends Person 
{
 
//Attribute 
  //Functionen
 
public function ID()
  {
    echo
"<p>I am a student</p>"
  }
}
?>
2017-05-31 20:22:27
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
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:

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

<?php
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.
2017-06-08 13:30:20
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
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
}
2017-06-12 01:50:36
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html
Автор:
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.

<?php
//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');
});
2017-07-26 11:10:23
http://php5.kiev.ua/manual/ru/language.oop5.inheritance.html

    Поддержать сайт на родительском проекте КГБ