downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Scope Resolution Operator (::)> <Visibility
Last updated: Fri, 23 Jul 2010

view this page in

Object Inheritance

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 you extend a class, the subclass inherits all of the public and protected methods 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.

Przykład #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'

?>


Scope Resolution Operator (::)> <Visibility
Last updated: Fri, 23 Jul 2010
 
add a note add a note User Contributed Notes
Object Inheritance
jackdracona at msn dot com
15-Apr-2010 03:53
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
 
?>
php at sleep is the enemy dot co dot uk
07-Apr-2010 09:36
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;
    }
   
}
?>
php at sleep is the enemy dot co dot uk
31-Mar-2010 03:47
Here's some example usage of the mixin class.

<?php

class Lunch extends Mix {
   
    public
$edible = true;
   
   
/*
     * Circular references are, of course, illegal and will be detected
     */
    /*
    public function mixinSteakAndKidneyPie($method, $args){
        return SteakAndKidneyPie::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
    }
    //*/
   
   
public function isEdible($affirm, $negate){
        return
$this->edible ? $affirm : $negate;
    }
}

class
Pie extends Mix {
   
   
/*
     * class tokens are bound at compile time so need to be explicitly declared
     * Need to make sure there are enough argument placeholders to cover all mixed in methods of Lunch
     * Late static binding may improve this situation
     */
   
public function mixinLunch($method, $args){
        return
Lunch::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
    }
   
    public function
buildPie($sep = ','){
        return
'Crust' . $sep . $this->getFilling() . $sep . 'More Crust';
    }
   
    public function
getFilling(){
       
$this->edible = false;
        return
'Baking beans';
    }
}

class
SteakAndKidney extends Mix {
   
    public function
mixinLunch($method, $args){
        return
Lunch::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
    }
   
   
/*
     * everything to be mixed in must be public
     * protected/private methods called from within mixed in methods will fail
     */
   
public $filling = 'Steak and Kidney';
   
    public function
getFilling(){
       
$this->edible = true;
        return
$this->filling;
    }
}

class
SteakAndKidneyPie extends Mix {
   
   
   
/*
     * order of mixin declaration significant
     * later declarations override earlier ones
     */
   
public function mixinSteakAndKidney($method, $args){
        return
SteakAndKidney::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
    }
   
    public function
mixinPie($method, $args){
        return
Pie::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
    }
   
   
/*
     * Pick specific methods like so:
     */
    //*
   
public function getFilling(){
        return
SteakAndKidney::getFilling();
    }
   
//*/
   
}

$pie = new SteakAndKidneyPie();
echo
$pie->buildPie(' | ');
echo
'<br/>Pie ' . $pie->isEdible('is', 'is not') . ' Edible';

/*
OUTPUTS:
Crust | Steak and Kidney | More Crust
Pie is Edible
*/

?>
jarrod at squarecrow dot com
27-Oct-2009 02:01
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!

?>

Scope Resolution Operator (::)> <Visibility
Last updated: Fri, 23 Jul 2010
 
 
show source | credits | sitemap | contact | advertising | mirror sites