En esta entrada vamos a explorar un nuevo mecanismo de reutilización de código que incorpora la versión 5.4 del lenguaje de programación PHP. Esta forma evita heredar de una clase padre o reescribir código una y otra vez.
La forma clásica de ampliar la funcionalidad a una clase (sin modificarla) es heredar de ella y en la clase hija implementar esa funcionalidad extra. Si la clase padre está programada correctamente (por ejemplo, usando los late-static bindings en sus métodos estáticos), la clase hija será un clon, en funcionalidad, del padre.
El problema de este enfoque es que, en muchos lenguajes y entre ellos en PHP, la herencia de implementación es simple. Los motivos por los que las implementaciones de lenguajes no soportan herencia múltiple son variados. En primer lugar es ineficiente ya que ante una llamada, el intérprete debería realizar introspección para ver qué padre es el que contiene la implementación. En segundo lugar, puede causar confusión; el caso típico es aquél en el que dos padres implementan un método con el mismo nombre y número de parámetros ¿cuál se ejecuta en la llamada desde la clase hija? Para no tener que lidiar con estos problemas, los desarrolladores de PHP decidieron que una clase hija no pudiera heredar de varias clases padre, al contrario de como pasa en otros lenguajes como C++.
No podemos cambiar el comportamiento de los objetos de una clase mediante herencia. La herencia, metodológicamente hablando, permite dar entidad a una clase, pero no debemos confundir esto con añadir funcionalidad.
La solución a este problema es usar algún mecanismo que permite introducir funcionalidad de manera que no se cambie la entidad de la clase, de ahí el término “herencia horizontal”. Para esto, le acoplamos unidades de funcionalidad independientes y carentes de entidad propia llamadas Mixins. En PHP 5.4 se implementan los Mixins con el nombre de Traits y su uso es sencillo.
Valga el siguiente ejemplo. Queremos darle funcionalidad de visualización de usuarios y de creación de URLs a un controlador. Para ello definidos los traits y los usamos desde nuestra clase. PHP permite sobrescribir los métodos usados,
Hay que tener en cuenta que si la clase actual tiene un método con el mismo nombre que un trait, se llamará al de la clase y no al del trait. Pero si hereda de otra clase, el trait si sobrescribe los métodos de esta clase base. De manera que la precedencia será la siguiente:
Internamente PHP lo único que hace es añadir el código de los traits a la clase, de manera que estamos realmente ante un artificio que los desarrolladores del intérprete de PHP han creado para permitir añadir el código copiándolo a una clase, todo esto sin cambiar el motor de esta plataforma. Es decir, nos quedamos con lo que cuenta el usuario greywire en la página de la documentación:
Otras características que pueden interesar a los desarrolladores son la definición de atributos estáticos, propiedades, métodos abstractos en los traits, y composición entre traits. Dejaremos estos aspectos algo más avanzados para otra entrada, en la que esperamos que PHP 5.4 esté en versión estable.
Si quieres saber más sobre este mecanismo que nos facilitará la vida: http://php.net/manual/en/language.oop5.traits.php
Diego J. Romero
La forma clásica de ampliar la funcionalidad a una clase (sin modificarla) es heredar de ella y en la clase hija implementar esa funcionalidad extra. Si la clase padre está programada correctamente (por ejemplo, usando los late-static bindings en sus métodos estáticos), la clase hija será un clon, en funcionalidad, del padre.
El problema de este enfoque es que, en muchos lenguajes y entre ellos en PHP, la herencia de implementación es simple. Los motivos por los que las implementaciones de lenguajes no soportan herencia múltiple son variados. En primer lugar es ineficiente ya que ante una llamada, el intérprete debería realizar introspección para ver qué padre es el que contiene la implementación. En segundo lugar, puede causar confusión; el caso típico es aquél en el que dos padres implementan un método con el mismo nombre y número de parámetros ¿cuál se ejecuta en la llamada desde la clase hija? Para no tener que lidiar con estos problemas, los desarrolladores de PHP decidieron que una clase hija no pudiera heredar de varias clases padre, al contrario de como pasa en otros lenguajes como C++.
No podemos cambiar el comportamiento de los objetos de una clase mediante herencia. La herencia, metodológicamente hablando, permite dar entidad a una clase, pero no debemos confundir esto con añadir funcionalidad.
La solución a este problema es usar algún mecanismo que permite introducir funcionalidad de manera que no se cambie la entidad de la clase, de ahí el término “herencia horizontal”. Para esto, le acoplamos unidades de funcionalidad independientes y carentes de entidad propia llamadas Mixins. En PHP 5.4 se implementan los Mixins con el nombre de Traits y su uso es sencillo.
Valga el siguiente ejemplo. Queremos darle funcionalidad de visualización de usuarios y de creación de URLs a un controlador. Para ello definidos los traits y los usamos desde nuestra clase. PHP permite sobrescribir los métodos usados,
class UrlGenerator { public static function actionUrl($parameters) { return makeUrl( __CLASS__.”/*/$parameters” ); } public static function rootUrl() { return makeUrl( __CLASS__ ); } } class UserView { protected static function show($user) { print “Usuario “.$user->getName(); } } class UserController { use UrlGenerator, UserView { // Renombramos en UserController el nombre del método de un trait // También le cambiamos la visibilidad UserView::show as public showUser; } /** * Visualización de la aplicación */ public static function show() { $users = self::dbLoadAll(); foreach($users as $user) { print self::actionUrl($user->getId()“/edit”); print self::actionUrl($user->getId()“/delete”); self::showUser($user); } } }
Hay que tener en cuenta que si la clase actual tiene un método con el mismo nombre que un trait, se llamará al de la clase y no al del trait. Pero si hereda de otra clase, el trait si sobrescribe los métodos de esta clase base. De manera que la precedencia será la siguiente:
Internamente PHP lo único que hace es añadir el código de los traits a la clase, de manera que estamos realmente ante un artificio que los desarrolladores del intérprete de PHP han creado para permitir añadir el código copiándolo a una clase, todo esto sin cambiar el motor de esta plataforma. Es decir, nos quedamos con lo que cuenta el usuario greywire en la página de la documentación:
The best way to understand what traits are and how to use them is to look at them for what they essentially are: language assisted copy and paste
.
Otras características que pueden interesar a los desarrolladores son la definición de atributos estáticos, propiedades, métodos abstractos en los traits, y composición entre traits. Dejaremos estos aspectos algo más avanzados para otra entrada, en la que esperamos que PHP 5.4 esté en versión estable.
Si quieres saber más sobre este mecanismo que nos facilitará la vida: http://php.net/manual/en/language.oop5.traits.php
Diego J. Romero
Esta característica nueva de PHP5.4 es muy potente y otra forma de entenderla es que podemos hacer parecido a esta "burrada" que, evidentemente, no funciona en ninguna versión de PHP:
ResponderEliminarclass MiClase {
include "mis_metodos_1.php";
include "mis_metodos_2.php";
public function otroMetodo(){
....
}
}
Donde los ficheros incluidos tendrían únicamente definiciones de métodos.