extends : héritage

Souvent, vous aurez besoin d'une classe avec des méthodes et fonctions similaires à une autre classe. En fait, il est bon de définir des classes génériques, qui pourront être réutilisées et adaptées à tous vos projets. Pour faciliter cela, une classe peut être une extension d'une autre classe. La classe dérivée hérite alors de toutes les méthodes et variables de la classe de base (cet héritage a de bien que personne ne meurt pour en profiter), mais peut définir ses propres fonctions et variables, qui s'ajouteront. Une classe ne peut hériter que d'une seule autre classe, et l'héritage multiple n'est pas supporté. Les héritages se font avec le mot clé 'extends'.

<?php
class Panier_nomme extends Panier {
    var 
$owner;
  
    function 
set_owner ($name) {
        
$this->owner $name;
    }
}
?>

L'exemple ci-dessus définit la classe Panier_nomme qui possède les mêmes variables que la classe Panier et la variable $owner en plus, ainsi que la fonction set_owner(). Vous créez un panier nominatif de la même manière que précédemment, et vous pouvez alors affecter un nom au panier ou en connaître le nom. Vous pouvez de toutes les façons utiliser les mêmes fonctions que sur un panier classique.

<?php
$ncart 
= new Panier_nomme;    // Création d'un panier nominatif
$ncart->set_owner ("kris");   // Affectation du nom du panier
print $ncart->owner;           // Affichage du nom du panier
$ncart->add_item ("10"1);   // (héritage des fonctions de la classe père)
?>

Ceci est également appelé une relation "parent-enfant". Vous créez une classe parent, et utilisez extends pour créer une nouvelle classe basée sur la classe parent : la classe enfant. Vous pouvez toujours utiliser cette nouvelle classe enfant et en créer une nouvelle basée sur cette classe enfant.

Note:

Les classes doivent être définies avant d'être utilisées ! Si vous voulez que la classe Named_Cart étende la classe Cart, vous devez d'abord définir la classe Cart. Si vous voulez créer une autre classe appelée Yellow_named_cart, basée sur la classe Named_Cart, vous devez d'abord définir la classe Named_Cart. Pour faire court : l'ordre dans lequel les classes sont définies est important.

add a note add a note

User Contributed Notes 22 notes

up
24
bilalghouri at live dot com
14 years ago
One thing I figured out after a long time about extending a parent class that, if the child class does not have any construct function, it will use its parent's construct.

for example:

<?php
class Main
{
    public
$a;
   
    public function
__construct()
    {
        echo
'::Parent Class initiated::';
       
       
$this -> a = 'we are in the parent class';
    }
}

class
Child extends Main
{
    public function
getA()
    {
        return
$this -> a;
    }
}

$main = new Main();
$main -> child = new Child;

echo
$main -> child -> getA();

//Output - ::Parent Class initiated::::Parent Class initiated::we are in the parent class
?>

However, If we have a constructor in the child class as well:

<?php
class Child extends Main
{
    public function
__construct()
    {
       
    }
    public function
getA()
    {
        return
$this -> a;
    }
}
?>

Then :

<?php
$main
= new Main();
$main -> child = new Child;

echo
$main -> child -> getA();

// Output - ::Parent Class initiated::
?>

Note that the parent variable 'a' is not inherited by the child class if the constructor from the parent class isnt called.
This behaviour of extension made me waste a lot of my precious time, as I could not understand why some of my child classes were inheriting parent variables and some were not.
Hope this helps someone..
up
17
bpotier at edreamers dot org
23 years ago
Just one thing that may seem obvious but not mentionned in this page is that you need to include/require the file containing the parent class or else you'll get an error:

<?php
require(dirname(__FILE__).'/'.'myParent.php');
// ...
myChild extends myParent {
 
// ...
}
// ...
?>
up
8
Edward_nl
18 years ago
If you are using a child-class. Remember to call the constructor of the parent class aswell before you start using it. Otherwise you might get different results then you expected. It is stated in this document, but I got confused by the given example. So, here is my example:

<?php
error_reporting
(E_ALL);

class
test {
  var
$var;

  function
test() {
   
$this->var = 3;
  }
}

class
testing extends test {
   function
testing() {
    
parent::test();
   }

   function
My_test() {
     return
$this->var;
   }
}

$p = new testing();
echo
$p->My_test();
// Returns 3
up
11
f4bi0_ at hotmail dot com
14 years ago
<?php
// what if we want to extend more then one class?

Abstract class ExtensionBridge
{
   
// array containing all the extended classes
   
private $_exts = array();
    public
$_this;
       
    function
__construct(){$_this = $this;}
   
    public function
addExt($object)
    {
       
$this->_exts[]=$object;
    }
   
    public function
__get($varname)
    {
        foreach(
$this->_exts as $ext)
        {
            if(
property_exists($ext,$varname))
            return
$ext->$varname;
        }
    }
   
    public function
__call($method,$args)
    {
        foreach(
$this->_exts as $ext)
        {
            if(
method_exists($ext,$method))
            return
call_user_method_array($method,$ext,$args);
        }
        throw new
Exception("This Method {$method} doesn't exists");
    }
   
   
}

class
Ext1{
private
$name="";
private
$id="";
public function
setID($id){$this->id = $id;}
public function
setName($name){$this->name = $name;}
public function
getID(){return $this->id;}
public function
getName(){return $this->name;}
}

class
Ext2{
private
$address="";
private
$country="";
public function
setAddress($address){$this->address = $address;}
public function
setCountry($country){$this->country = $country;}
public function
getAddress(){return $this->address;}
public function
getCountry(){return $this->country;}
}

class
Extender extends ExtensionBridge
{
    function
__construct()
    {
       
parent::addExt(new Ext1());
       
parent::addExt(new Ext2());
    }
   
    public function
__toString()
    {
        return
$this->getName().', from: '.$this->getCountry();
    }
}

$o = new Extender();
$o->setName("fabio");
$o->setCountry("brazil");
echo
$o;
?>
don't hesitate to email me, happy coding! ;)
up
5
Adel Abula adel at magebinary dot com
9 years ago
You can always place the universal variables and functions into the deepest class. Then call or rewrite it in child classes. See example.

<?php

class ClassA
{
    public
$var;
    function
__construct()
    {
       
$this->setVar();
       
$this->getVar();
    }

    protected function
getVar()
    {
        echo
$this->var;
    }

    public function
setVar()
    {
       
$this->var = 1000;
    }
}

class
ClassAChildA extends ClassA
{

    function
__construct()
    {
       
$this->setVar();
       
$this->getVar();
    }

    public function
setVar()
    {
       
$this->var = 1001;
    }
}

class
ClassAChildB extends ClassA
{
    function
__construct()
    {
       
$this->var = 1002;
       
$this->getVar();
    }

    public function
getVar()
    {
        echo
$this->var;
    }
}
//prints 1000
$parent = new ClassA();

//prints 1001
$childA = new ClassAChildA();

//prints 1002
$childB = new ClassAChildB();
?>
up
3
volte6 at nowhere dot com
19 years ago
When declaring a class that relies upon another file ( because it extends the class defined in that file ), you should ALWAYS require_once() that file at the top.
This applies even when planning on looping through and including everything in the folder. Use require_once() in your loop, and at the top of the file that NEEDS the include.
up
6
geilt at esotech dot org
12 years ago
I have found this the best way to grab a parents variables and such (that I love to set in the constructor, like standardized table names, etc.). I just call the parents constructor in the child constructor, then change variables inside the child constructor that needs to be customized for that class, or just leave it alone to make sure I understand I am using the parents constructor in the child constructor. (it's a good note and practice of mine.).

<?php
class MyParentClass
{
   
$this->table_one = "my_table";
   
$this->table_two = "variable_table";
}

class
MyChildClass extends MyParentClass
{
    public function
construct()
    {
       
parent::__construct();

       
$this->table_two = "newly_defined_table";

    }
    public function
action()
   {
     
$table1 = $this->table_one;
     
$table2 = $this->table_two;

      return
$table1 . " - " . $table2;
   }
}

$myChildClass = new MyChildClass;

echo
$myChildClass->action();

//Displays my_table - newly_defined_table
?>
up
5
mazsolt at yahoo dot com
21 years ago
Just a simple example about inheritance:

<?php
class a1{
  var
$a=10;
  function
a1($a){
    
$this->a=$a;
  }
}

class
a2 extends a1{
  var
$x=11;
  function
a2($x,$y){
    
$this->x=$x;
    
parent::a1($y); // or a1::a1($y) or $this->a1($y)
 
}
}

class
a3 extends a2{
  var
$q=999;
}

$x=new a3(99,9);
echo
$x->a,"<br>",$x->x,"<br> ",$x->q;
?>

The output will be:

9
99
999
up
2
tomnezvigin at comcast dot net
19 years ago
This may seem obvious, but check this scenario. You have a class folder:

+ class
--classA.php
--classB.php
--classC.php
--mainClass.php

Here... classA, classB, classC all extend the mainClass.

If you try to create a function that automatically includes all of the classes in a folder, normally, they are included alphabetically.

When you try to instantiate classC, for example, you will get an error:

"Cannot inherit from undefined class mainClass"

EVEN IF you instantiate the mainClass before you instantiate all of the other classes.

In other words, make sure your primary class is included before all others.
up
1
Bash I.
19 years ago
Here is a simple idea that I use when I need my abstract classes (the inherited classes) implemented before my functional classes.

<?php
   
    $_CLASSES
= array_merge (
       
glob ("classes/*/*.abstract.php"),
       
glob ("classes/*/*.class.php")
    );
   
    foreach (
$_CLASSES AS $_CLASS) {
        require (
$_CLASS);
    }
   
?>
up
1
efredin at redtempest dot com
20 years ago
It is possible to override a method innherited from a parent class by simply re-defining the method (for those of us who enjoy using abstract classes).

<?php
class A
{
    var
$foo;

    function
A()
    {
       
$this->foo = "asdf";
    }
   
    function
bar()
    {
        echo
$this->foo." : Running in A";
    }
}

class
B extends A
{
    function
bar()
    {
        echo
$this->foo." : Running in B";
    }
}

$myClass = new B;
$myClass->bar();
?>
up
2
datahell at elxis dot org
13 years ago
If you have a class that extends an other and both classes have a function with the same name then visibility to both classes should be the same, else you will have a fatal error.

An other interested part in the example bellow is that if visibility of the showName method is private then $this->name() will execute the showName method on class test. If it is public or protected it will execute method showName on class extendTest.

<?php
class test {

    public function
__construct() {
    }

    public function
name() {
       
$this->xname('John');
    }

    private function
showName($name) {
        echo
'my name in test is '.$name;
    }
}

class
extendTest extends test {

    public function
__construct() {
       
parent::__construct();
    }

    private function
showName($name) {
        echo
'my name in extendTest is '.$name;
    }
}

$test = new extendTest();
$test->name();
?>

result: my name in test is John

If we change visibility of the showName method to public or protected then the result of the above will be:
my name in extendTest is John
up
3
calimero at creatixnet dot com
21 years ago
Just a quick note to make things more clear : while multiple inheritance is not allowed, several levels of single inheritance  ARE ALLOWED indeed. Just test this example :

<?php
class A {
    var
$name='A';

    function
disp() {
        echo
$this->name;
    }
}

class
B extends A {
    var
$name='B';
}

class
C extends B {
    var
$name='C';
}

$truc = new C() ;
$truc->disp(); // Will output C
?>

This is especially important to keep in mind while building a huge object hierarchy. for example :

+GenericObject
->+ Person
->->Employee
->+Computer
->->+WorkStation
->->-> PPC
->->-> Intel
->->+Server
->->->LDAPServer
->->->IntranetWebServer

.. and so on. Multiple level hierarchy relationship are possible in a tree-like structure (each child has one and only one parent, except for the root object).
up
1
alan hogan
18 years ago
Just a note:  It is possible to have a class inherit from multiple other classes, but only in a one-at-a-time linear hierarchy.

So this works, and C gets A and B functions:

<?php
class A {
  public function
af() { print 'a';}
  public function
bark() {print ' arf!';}
}
class
B extends A {
  public function
bf() { print 'b';}
}
class
C extends B {
  public function
cf() { print 'c';}
  public function
bark() {print ' ahem...'; parent::bark();}
}

$c = new C;
$c->af(); $c->bf(); $c->cf();
print
"<br />";
$c->bark();
/**results:**/
//abc
//ahem... arf!
?>

This does NOT work:

<?php
class A {
  public function
af() { print 'a';}
  public function
bark() {print ' arf!';}
}
class
B {
  public function
bf() { print 'b';}
}
class
C extends B, A /*illegal*/ {
  public function
cf() { print 'c';}
  public function
bark() {print ' ahem...'; parent::bark();}
}

$c = new C;
$c->af(); $c->bf(); $c->cf();
print
"<br />";
$c->bark();
//Parse Error
?>
up
1
admin at dmsoft-wy dot com
14 years ago
You don't need to include_once the parent class if it's already declared.  You do have to load the parent first and then the child.
up
1
vittorio dot zamparella at gmail dot com
9 years ago
extending a PHP class with an included file "delays" the compilation:

<?php
require 'MySuperclass.php';
var_dump(class_exists('MyFirstClass')); // FALSE
class MyFirstClass extends MySuperclass {}
   
// the "compilation" of this is delayed till execution
var_dump(class_exists('MyFirstClass')); // TRUE

class AnotherSuperclass { /* nothing */}
var_dump(class_exists('MySecondClass'));
   
// returns TRUE even if it's called "before" definition
class MySecondClass extends AnotherSuperclass {}
?>

see also the examples at http://php.net/manual/en/function.class-exists.php

discoverd this when autoinitializing some static classes
up
0
"inerte" is my hotmail.com username
22 years ago
[Editor's note: For an alternative to multiple inheritance, see the dynamic binding via object aggregation in the corresponding section of the manual.]

Multiple Inheritance is not supported but it is easy to emulate it:

<?php
class multipleInheritance
{
    function
callClass($class_to_call)
    {
        return new
$class_to_call();
    }
}

class
A
{
    function
insideA()
    {
        echo
"I'm inside A!<br />";
    }
}

class
B
{

    function
insideB()
    {
        echo
"I'm inside B!<br />";
    }
}

class
C extends multipleInheritance
{
    function
insideC()
    {
       
$a = parent::callClass('A');
       
$a->insideA();
       
$b = parent::callClass('B');
       
$b->insideB();
    }
}

$c = new C();
$c->insideC();
?>

---
This will succesfully echo:
I'm inside A!
I'm inside B!
up
0
griffon9 at hotmail dot com
22 years ago
Just to clarify something about inheritance. The following code :

<?php
class a
{
     function
call()
     {
         
$this->toto();
     }
    
     function
toto()
     {
          echo(
'Toto of A');
     }
}
 
class
b extends a
{
     function
toto()
     {
          echo(
'Toto of B');
     }
}

$b=new b;
$b->call();

?>

...will correctly display "toto of B" (that is, the function declared in the parent is correctly calling the redefined function in the child)
up
0
php_AT_undeen_DOT_com
22 years ago
if the class B that extends class A does not have a constuctor function (i.e. a function named B), then the constructor function of A will be used instead, you don't need to make a constructor in B just to call the constructor of A.

For example:

<?php
class A
{
  function
A()
    {
      echo
"HEY! I'm A!\n";

    }
}

class
B extends A
{
}

$b = new B();
?>

produces the output:
HEY! I'm A!
up
-1
Frank
14 years ago
Just a quick example of how PHP will handle a parent calling a function named in both the parent and the child class.  You would think it might use the function the way it is defined in the parent, but it does use the function that is defined in the child.

<?php
class One{
    function
showOne(){
        echo
'Function One prints';
    }
    function
hitFunction(){
       
$this->showOne();
    }
}
class
Two extends One{
    function
showOne(){
        echo
'Function Two prints';
    }
}

$thistwo = new Two;
$thistwo->hitFunction(); //prints "Function Two prints"
?>
up
-1
Msquared
20 years ago
Multiple inheritence is often more trouble than it's worth.  For example, you have a class foo that inherits from both class bar and class baz.  Classes bar and baz both have a fubar() method.  When you create a foo object and call its fubar() method, which fubar() method is called: bar's or baz's?

It seems to me that using aggregate to glue one class's methods and data to another object is a bit like Ruby's fixins, but I could be wrong...

[[Editor's note:
The aggregate_* functions have been dropped, as of PHP 5
-S
]]
up
-1
schultz at rancon dot de
22 years ago
This prints out 'ab'.  No need to create a new instance of a, therefor both methods still exists with same name.

<?php

class a {
  function
samename(){
    echo
'a';
  }
}

class
b extends a{
  function
samename(){
    echo
'b';
  }
  function
b(){
   
a::samename();
   
b::samename();
  }
}

$test_obj = new b();
?>
To Top