martes, 15 de julio de 2025

07 Php POO Herencia Múltiple Traits

 En Php no se permite la herencia múltiple, sólo se permite la herencia simple.

Una clase sólo puede heredar de una clase padre, para simular la herencia múltiple podemos usar los traits.
Si quisiera tener dos clases padre, a la segunda clase padre no la definiré como class, sino como traits.
Y para extender esta segunda clase padre, dentro de la clase hija, definiremos dentro de la clase hija el trait:
                class Persona00{ }
                trait Persona01{ }
                class Persona02 extendes Persona00{ use Persona01; }

Con esto logramos extender la clase Persona00 y la clase Persona01.
Lo mismo podríamos hacer dentro de un trait para extender otros.

Una de las diferencias entre los traits y las clases es que los traits no se pueden instanciar.

Precedencia:
Que sucedería si la clase padre tuviese un método que se llama igual en el trait que extiende a esta?
El trait sobrescribe a todos los métodos y propiedades de la clase padre.

Podemos utilizar traits múltiples.
Si en un trait existen métodos con el mismo nombre hemos de indicar cual vamos a utilizar, de lo contrario tendremos un error:
class Hijo01 extends Padre01{
                use TPadre02, TPadre03{
                               TPadre02::setMensaje insteadOf TPadre03;
                }
}

Del mismo modo podemos cambiar la visibilidad de un método protected definido en uno de los trait.
class Hijo01 extends Padre01{
                use TPadre02, TPadre03{
                               TPadre02::setMensaje2 as public;
                }
}

Podríamos definir clases abstractas dentro de un trait.
Esto nos obliga a declararla dentro de la clase o el trait que la extiende.
class Hijo01 extends Padre01{
                use TPadre02, TPadre03{
                                TPadre02::setMensaje2 as public;
                }
                public function setMensaje3(){
                                echo "* Clase Hijo01: Clase Abstracta setMesaje3...<br>";
                               $this->setMensaje();
                               $this->setMensaje2();
                }
} // Fin Clase Hijo01
$ObjHijo01 = new Hijo01;

$ObjHijo01 -> setMensaje3();

Ejemplos:

// Php no permite la herencia múltiple, para esto usamos los traits.
class Padre01{
                public function setNombre($nombre){
                                echo "- Clase Padre01. Esto es mi nombre: ".$nombre."<br>";
                }
                public function setMensaje(){
                                echo "- Clase Padre01: Mensaje de la clase Padre01...<br>";
                }
}

// Clase TPadre02
trait TPadre02{
                public function setNombre2($apellido){
                                echo "- Clase Padre02. Esto es mi apellido: ".$apellido."<br>";
                }
                // Este método sobre escribe el metodo de la clase Padre01
                public function setMensaje(){
                                echo "- Trait Padre02: Mensaje del Trait02...<br>";
                }
                private function setMensaje2(){
                                echo "- Trait Padre02: Método Protegido...<br>";
                }
                // Declaro una clase abstracta...
                abstract public function setMensaje3();
}

trait TPadre03{
                public function setNombre3($Dato){
                                echo "- Trait Padre03: Esto es un dato: ".$Dato."<br>";
                }
                public function setMensaje(){
                                echo "- Trait Padre03: Mensaje del Trait03...<br>";
                }
}

// Clase hija con herencia multiple mediante traits.
class Hijo01 extends Padre01{
                //use TPadre02;

                // Uso de traits múltiples...
                // Como tenemos dos metodos con el mismo nombre en los trait TPadre02 y TPadre03 tenemos un error
                //use TPadre02, TPadre03;
                // De esta forma se soluciona el error: Indicamos cual es el método a utilizar...
                use TPadre02, TPadre03{
                                TPadre02::setMensaje insteadOf TPadre03;
                                TPadre02::setMensaje2 as public;
                }
                public function setMensaje3(){
                                echo "* Clase Hijo01: Clase Abstracta setMesaje3...<br>";
                                $this->setMensaje();
                                $this->setMensaje2();
                }

                // Este método sobre escribe el método del trait TPadre02 y TPadre03...
                /*
                public function setMensaje(){
                                echo "- Clase Hijo Herencia Multiple: Último mensaje...";
                }
                */
}

// Instanciamos el objeto $ObjHijo01 que hereda los métodos y propiedades de las dos clases padres.
$ObjHijo01 = new Hijo01;

// Accedemos a los métodos heredadeos en nuestro objeto y pasamos el parámetro requerido...
$ObjHijo01 -> setNombre("Juan Manuel");
$ObjHijo01 -> setNombre2("Barrós Pazos");

$ObjHijo01 -> setNombre3("Ojo al dato...");

// Se sobrescribe el método de la clase Padre01 en el trait Padre02 en el método de la clase Hijo01
$ObjHijo01 -> setMensaje();
$ObjHijo01 -> setMensaje2();

$ObjHijo01 -> setMensaje3();

// Los traits no se pueden instanciar en un objeto, esto nos da un error...
//$ObjTrait01 = new Padre02;
//$ObjTrait01 -> setNombre2("Ana María");

// Precedencia: El trait sobrescribe a todos los métodos y propiedades de la clase padre con el mismo nombre...

No hay comentarios:

Publicar un comentario

Gracias por vuestros aportes.