El blog de bCube

[bCube CMS]: ¿Sabías qué? Traits de PHP

Escrito por Jesús Cuenca | 30-mar-2023 8:58:42

Los traits en PHP permiten simular una herencia múltiple. El lenguaje de programación sólo soporta herencia simple, por lo que con los traits podemos utilizar múltiples clases en una clase. En este ¿sabías qué? explicamos detalladamente qué son los traits y cómo usarlos. 

 

PHP es un lenguaje que permite la programación orientada a objetos, por ello, posibilita el tener jerarquías de objetos, definiendo clases que hereden funcionalidad de otras clases para hacer el código más legible y reutilizable. Sin embargo, PHP sólo permite la herencia simple entre clases, lo que significa que una misma clase no puede heredar funcionalidad de otras dos clases a la vez. Por ello, PHP ofrece un método de reutilización de código adicional a la herencia: los Traits.


¿Qué son los traits?

Un Trait es similar a una clase, pero con el único objetivo de agrupar funcionalidades muy específicas y de una manera coherente. De hecho, la traducción literal de la palabra trait en inglés es rasgo o característica. En definitiva, es una forma de copiar y pegar código entre varios objetos del proyecto; de hecho, internamente, PHP lo único que hace es literalmente eso, copiar el código del trait en las clases que lo usan. A continuación, ofrecemos algunos datos interesantes sobre ellos:

  • Una clase puede utilizar más de un Trait.

  • Un Trait puede utilizar otros Traits.

  • No se puede instanciar directamente un Trait. Esto es así porque no son objetos como tal, son simplemente una forma de reutilizar código.

  • A pesar de que no se pueden instanciar directamente, se puede definir la función __construct dentro de un Trait. Sin embargo, esto se considera una mala práctica porque normalmente plantea más problemas que beneficios.

  • En un Trait se pueden definir tanto propiedades como funciones. Las funciones pueden ser normales, abstractas y estáticas.

  • Sin embargo, no se pueden definir constantes en un Trait. Para eso, lo mejor es utilizar una Interface.

  • No se puede saber fácilmente si una clase usa un Trait o no; existen formas de saberlo, pero un simple instanceof no funcionará. De nuevo, para ello lo mejor es definir una Interface.

  • Es posible cambiar la visibilidad de una propiedad o un método proporcionado por un Trait.

  • Es posible que dos Traits diferentes proporcionen la definición del mismo método. Se puede decidir cuál de ellos usar.

  • Se pueden crear alias para los métodos proporcionados por un Trait.

 

Definición y uso de traits

Los traits se definen de forma similar a una clase:

y se utilizan en una clase utilizando la palabra clave use:

Como hemos dicho, se pueden utilizar traits en clases que ya extienden de otras clases, siendo una manera adicional de compartir código entre clases además de la herencia:

 

Precedencia

Es posible que al utilizar Traits junto con herencia se llegue a la situación de que una misma clase obtiene diferentes definiciones de un mismo método o propiedad. Por ejemplo:

¿Cómo sabemos qué función será la que finalmente se usará en las instancias de la clase Article?

Recordemos que los Traits son, en realidad, un copia y pega de PHP para facilitarnos la herencia múltiple reutilización de código. Teniendo esto en mente, se puede deducir que los métodos definidos directamente en una clase sobrescriben a los métodos del Trait (como si de una herencia simple se tratase); por otro lado, los métodos de una clase sobrescriben a los métodos heredados de la clase padre, como siempre. Así pues:

  • La clase Content obtiene la definición de __toString del Trait:



  • La clase Article sobrescribe la definición de __toString tanto del Trait como de Content:



  • La clase Article obtiene la definición del método print del Trait, que a su vez sobrescribe la definición de Content (como en una herencia normal):

Como hemos visto, dos Traits diferentes pueden proporcionar a una clase el mismo método. Esto puede llevar a situaciones no deseadas, donde PHP utilice el método del Trait que no interese.

Por ello, PHP permite dar precedencia al método de un Trait sobre el de otro: para ello, utilizaremos la palabra clave insteadof.

También tenemos la opción de renombrar el método de uno de los Traits para que no coincida con el del otro, usando la palabra clave as; de esta forma, podemos tener ambas definiciones en métodos con diferente nombre:

 

Modificando la visibilidad de los métodos

Utilizando la palabra clave as también podemos cambiar la visibilidad de los métodos que nos proporcionan los Traits:

Jesús Cuenca es analista programador de Bitban Technologies.