Is Multiple Inheritance Allowed at Class Level in PHP

Is Multiple Inheritance allowed at class level in PHP?

Multiple inheritance suffers from the Diamond Problem, which has not been (agreed upon how to be) solved in PHP yet. Thus, there is no multiple inheritance in PHP.

    BaseClass
/\
/ \
ClassA ClassB
\ /
\/
ClassC

If both ClassA and ClassB defined their own method foo(), which one would you call in ClassC?

You are encouraged to either use object composition or interfaces (which do allow multiple inheritance) or - if you are after horizontal reuse - look into the Decorator or Strategy pattern until we have Traits (or Grafts or whatever they will be called then).

Some Reference:

  • [PHP-DEV] Traits,Grafts, horizontal reuse
  • [PHP-DEV] Multiple class inheritance
  • RFC: Traits for PHP
  • Traits-like Functionality in PHP now

Multiple Inheritance in PHP

Alex, most of the times you need multiple inheritance is a signal your object structure is somewhat incorrect. In situation you outlined I see you have class responsibility simply too broad. If Message is part of application business model, it should not take care about rendering output. Instead, you could split responsibility and use MessageDispatcher that sends the Message passed using text or html backend. I don't know your code, but let me simulate it this way:

$m = new Message();
$m->type = 'text/html';
$m->from = 'John Doe <jdoe@yahoo.com>';
$m->to = 'Random Hacker <rh@gmail.com>';
$m->subject = 'Invitation email';
$m->importBody('invitation.html');

$d = new MessageDispatcher();
$d->dispatch($m);

This way you can add some specialisation to Message class:

$htmlIM = new InvitationHTMLMessage(); // html type, subject and body configuration in constructor
$textIM = new InvitationTextMessage(); // text type, subject and body configuration in constructor

$d = new MessageDispatcher();
$d->dispatch($htmlIM);
$d->dispatch($textIM);

Note that MessageDispatcher would make a decision whether to send as HTML or plain text depending on type property in Message object passed.

// in MessageDispatcher class
public function dispatch(Message $m) {
if ($m->type == 'text/plain') {
$this->sendAsText($m);
} elseif ($m->type == 'text/html') {
$this->sendAsHTML($m);
} else {
throw new Exception("MIME type {$m->type} not supported");
}
}

To sum it up, responsibility is split between two classes. Message configuration is done in InvitationHTMLMessage/InvitationTextMessage class, and sending algorithm is delegated to dispatcher. This is called Strategy Pattern, you can read more on it here.

Multiple Inheritance Support

Multiple inheritance is not hard to add, the reason why so many languages don't include it is because it's a bit esoteric and messy. Multiple inheritance usually mixes up code, causes poor encapsulation, and makes code behave unpredictably. Usually a allowing multiple inheritance in code just causes a plethora of bad programming to come from that language usually resulting in giving the language a bad reputation. If multiple inheritance is needed for some a reason in that language, a coder who is smart enough to use it properly would most likely be smart enough to write their own method that would do it.

Can I extend a class using more than 1 class in PHP?

If you really want to fake multiple inheritance in PHP 5.3, you can use the magic function __call().

This is ugly though it works from class A user's point of view :

class B {
public function method_from_b($s) {
echo $s;
}
}

class C {
public function method_from_c($s) {
echo $s;
}
}

class A extends B
{
private $c;

public function __construct()
{
$this->c = new C;
}

// fake "extends C" using magic function
public function __call($method, $args)
{
$this->c->$method($args[0]);
}
}

$a = new A;
$a->method_from_b("abc");
$a->method_from_c("def");

Prints "abcdef"

Is Multiple Inheritance allowed at class level in PHP?

Multiple inheritance suffers from the Diamond Problem, which has not been (agreed upon how to be) solved in PHP yet. Thus, there is no multiple inheritance in PHP.

    BaseClass
/\
/ \
ClassA ClassB
\ /
\/
ClassC

If both ClassA and ClassB defined their own method foo(), which one would you call in ClassC?

You are encouraged to either use object composition or interfaces (which do allow multiple inheritance) or - if you are after horizontal reuse - look into the Decorator or Strategy pattern until we have Traits (or Grafts or whatever they will be called then).

Some Reference:

  • [PHP-DEV] Traits,Grafts, horizontal reuse
  • [PHP-DEV] Multiple class inheritance
  • RFC: Traits for PHP
  • Traits-like Functionality in PHP now

Codeigniter and Multiple Inheritance?

Multiple inheritance is not possible. You either can use interfaces or you can use the visitor designpattern like this:

<?php

class A {
public $avar = 'I\'m A';
function accept(Visitor $v){
$v->visitA($this);
}
}

class B {
public $bvar = 'B reporting';
function accept(Visitor $v){
$v->visitB($this);
}
}

class Visitor {
function visitA(A $a){
echo $a->avar;
}

function visitB(B $b){
echo $b->bvar;
}
}

$A = new A();
$B = new B();
$visitor = new Visitor();

$A->accept($visitor);
$B->accept($visitor);

?>

unfortunately php is not ready yet for distinguishing method calls by their parameter like in java where this example would look like that:

class A {
public String avar = 'I\'m A';
function accept(Visitor v){
v.visit(this);
}
}

class B {
public String bvar = 'B reporting';
function accept(Visitor v){
v.visit(this);
}
}

class Visitor {
function visit(A a){
System.out.println(a.avar);
}

function visit(B b){
System.out.println(b.bvar);
}
}

A = new A();
B = new B();
visitor = new Visitor();

A.accept(visitor);
B.accept(visitor);

where you have multiple visit methods distinguished by the type of their parameters

What is the difference between Multiple Inheritance and Polymorphism?

Like Ikke said, Multiple Inheritance has nothing to do with Polymorphism.

If I could draw a class diagram, Multiple Inheritance looks like this:

Base A    Base B
^ ^
\ /
\ /
Child

So, the class Child would inherit both attributes and behaviours from both classes. Many languages like Java and PHP don't allow this, but Python does.

Polymorphism, on the other hand, is when you can abstract out a specialisation. First of all, class diagram:

     Animal
^ ^
/ \
/ \
Cat Dog

And you may do the following:

// Assuming we have a pack of animals
// This is Java
for (Animal pet : pack)
pet.speak();

Each pet will say different things depending on the implementation.

Multi-level inheritance in PHP classes

My initial thought was that this may not be good for inheritance but after testing it seems okay. However, there are other means of accomplishing this you could be aware of.

Abstract classes or Interfaces may make sense.

Abstract classes are just like other classes but they cannot be instantiated. There are also abstract methods which must be implemented by concrete classes.

abstract class A {
//You can also have abstract methods
abstract public function doFoo();
abstract public function doBar($when);

//Also implemented method which when
//called unless overridden will use this logic
public function sayHi(){
echo "hi";
}
}

Now this class can choose to implement the abstract methods or not also adding any further logic needed by it.

abstract class B extends A {
public function doFoo(){
//Some code
}
abstract public function doFooBar();
public function sayBye(){
echo "bye";
}
}

This is a concrete class and all abstract methods must be implemented here if not already ones that are implemented can be overridden yet again.

class C extends B {
public function doFoo(){
//Some different code
}
public function doBar($when){
//Some code
}
public function doFooBar(){
//Some code
}

//do not need sayHi() and sayBye() but they will be available.
}

Interface in a simple and crude way is a bag of methods. You are simply telling the developer if you are going to use this implement these. These methods are not declared as abstract but cannot be implemented in the interface.

interface iA {
public function doFoo();
public function doBar();
}

An interface can be extended by other interface which is just adding more methods to the interface

interface iB extends iA {
public function doFooBar();
}

interface iC {
public function doAnything();
}

And implemented by classes

class A implements iA{
public function doFoo(){
//Some Code
}
public function doBar(){
//Some Code
}
}

class B implements iB{
public function doFoo(){
//Some Code
}
public function doBar(){
//Some Code
}
public function doFooBar(){
//Some Code
}
}

The added advantage of interfaces is that a class or abstract can implement more then one

abstract class C implements iA, iC {
public function doFoo(){
//Some Code
}
}

class D extends C {
//get doFoo() from C implementation and must implement the remaining...
public function doBar(){
//Some Code
}
public function doAnything(){
//Some Code
}
}


Related Topics



Leave a reply



Submit