PHP ¿Cómo heredar de dos o más clases?

Vamos a empezar por el principio, por defecto a día de hoy no se puede heredar de dos o más clases a la vez en php. Eso nos lo indica el manual de POO del manual oficial de PHP.

Ahora vamos con el supuesto:

  • Tengo una clase coche.
  • Tengo otra clase llamada coche_gasolina, que extiende coche.
  • Tengo otra clase llamada coche_electrico, que extiende coche.
  • Y tengo una clase llamada coche_hibrido.

La única solucción que me han propuesto en un foro es que la clase coche tuviese todo aquello que necesitásemos heredar tanto de la clase coche_gasolina como de la clase coche_eléctrico. No es mala solución, pero no me gusta porque se termina saturando la clase coche con métodos y atributos que posiblemente no necesite, más si tenemos en cuenta que igual hay que generar nuevas clases como coche_diesel, coche_hidrogeno, coche_solar, etc...

Otra posibilidad es crear interfaces y clases que representen las interfaces, en ese caso php si permite extender varias interfaces a la vez:

<?php
interface a
{
    public function
foo();
}

interface b
{
    public function
bar();
}

interface c extends a, b
{
    public function
baz();
}
?>

Aunque esta solución es totalmente útil y se puede usar le veo un problema a nivel operativo, para ello hay que entender que es una interfaces:

Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.

Esto significa que hay que definir la interfaces, enunciar los métodos, y luego cuando defines la clase crear el método y su código interior. Esto esta muy bien si queremos tener una interfaces y que clases muy parecidas hagan cosas diferentes en un momento dado. Pero en el caso de las clases coche_gasolina y coche_hibrido tendríamos que tener métodos idénticos y si cambiamos uno tenemos que recordar cambiar el otro.

La opción que más me gusta, pero que tampoco la considero perfecta, es algo similar a los interfaces y clases, pero en este caso usamos Traits. En este caso el código se queda en los traits, y las clases pueden usarlos. En este caso el problema que se puede tener es la colisión de nombre de métodos, aunque con política de definición de métodos por ejemplo: nombre_del_metodo_nombre_de_traits, un ejemplo sería:

<?php get_velocidad_punta_coche_electrico(){} ?>

<?php
trait Hello {
    public function
sayHello() {
        echo
'Hello ';
    }
}

trait World {
    public function
sayWorld() {
        echo
'World';
    }
}

class MyHelloWorld {
    use
Hello, World;
    public function
sayExclamationMark() {
        echo
'!';
    }
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>

Como he comentado al comienzo no existe una forma perfecta, pero si tenemos varias opciones para conseguir lo que necesitamos.