Multiple inheritance with PHP and Traits


Multiple inheritance isn’t allowed in PHP. With Python we can do things like that:

class ClassName(Base1, Base2):
    ....

That’s no possible with PHP (in Java is not possible either), but today we can do something similar (is not the exactly the same) with Traits. Let me explain that: Instead of classes we can create Traits:

<?php
trait Base1
{
    public function hello1($name)
    {
        return "Hello1 {$name}";
    }
} 

trait Base2
{
    public function hello2($name)
    {
        return "Hello2 {$name}";
    }
} 

And now we can use those traits (instead of to extend multiple classes)

<?php
class ClassName
{
    use Base1, Base2;
} 

The main reason because multiple inheritance isn’t allowed in PHP, Java and another languages is is due to the collisions. If we extends from two classes with the same method, which is the good one?
Python solves this problem with a easy solution: The first one is the good one:

class Base1:
    def hello1(self, name):
        return "Hello1 " + name

class Base2:
    def hello1(self, name):
        return "Hello2 " + name

class ClassName(Base1, Base2):
    pass
c = ClassName()
print c.hello1("Gonzalo")

Will output “Hello1 Gonzalo” but if change the inheritance order to:

class ClassName(Base2, Base1):
    pass

The output will be “Hello2 Gonzalo”

Traits in PHP doesn’t solve the problem “out of the box”. If we use the following script:

<?php
trait Base1
{
    public function hello1($name)
    {
        return "Hello1 {$name}";
    }
}

trait Base2
{
    public function hello1($name)
    {
        return "Hello2 {$name}";
    }
}

class ClassName
{
    use Base1, Base2;
}

$class = new ClassName();
echo $class->hello1("Gonzalo");

Our script will throw a Fatal error:

PHP Fatal error: Trait method hello1 has not been applied, because there are collisions with other trait methods on ClassName on line 23

If we want to avoid collisions, we need to describe explicitly what function we will use. It’s not difficult:

<?php
trait Base1
{
    public function hello1($name)
    {
        return "Hello1 {$name}";
    }
}

trait Base2
{
    public function hello1($name)
    {
        return "Hello2 {$name}";
    }
}

class ClassName
{
    use Base1, Base2 {
        Base1::hello1 insteadof Base2;
    }
}

$class = new ClassName();
echo $class->hello1("Gonzalo");

8 thoughts on “Multiple inheritance with PHP and Traits

  1. Yeah, it gets a little annoying writing, what should be, redundant code.

    What is the reason(s) a trait collision is resolved in this way and not like, for example, the python way?

  2. May be because the PHP’s implementation is more flexible?
    What will be if you have several methods with the same name and you should call some from trait1 and other from trait2

  3. “The main reason because multiple inheritance isn’t allowed in PHP, Java and another languages is is due to the collisions.”

    .. or maybe because its an inherently bad idea..

    1. inheritance or multiple inheritance? IMHO multiple inheritance is as good/bad as single inheritance. If you are saying single inherently is a bad idea I’m not 100% percent agree with you. But I must admit that with inheritance is very easy to violate a couple of SOLID values. Abstract classes has a trend to become ugly container of incoherent functions. In one code retreat someone said “inheritance is for losers”. Maybe he’s right 🙂

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.