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

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

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

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

Замечание:

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

Пример #1 Пример наследования


Наш чат в Telegram для обмена идеями, проектами, мыслями, людьми в сфере ИТ г.Ростова-на-Дону: @it_rostov
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'

User Contributed Notes 6 notes



11
strata_ranger at hotmail dot com3 years ago
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]


10
jackdracona at msn dot com3 years ago
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
 


7
jarrod at squarecrow dot com4 years ago
abstract class Cheese
{
      //can ONLY be inherited by another class
}
class Cheddar extends Cheese
{
}
$dinner = new Cheese; //fatal error
$lunch = new Cheddar; //works!


3
OZ3 years ago
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__.': '.$name, E_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__.': '.$property, E_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__.': '.$property, E_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__.': '.$method, E_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);
    }
}


-1
php at sleep is the enemy dot co dot uk3 years ago
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;
    }
    
}


-2
msg2maciej at aol dot com2 years ago
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;




Смотрите также:
Описание на ru2.php.net
Описание на php.ru