Clases para todo. Porque las clases son nuestras amigas. Y los objetos, que son sus hijos, nuestros compañeros de viaje. No se me ha ocurrido nada más cursi para comenzar, quizá es que no tengo muy claro ni lo que tengo que decir, ni cómo decirlo. ¡He visto la luz! Bueno, poco más o menos. A ver qué te parece esta definición de una clase: "Una clase es un tipo complejo de dato capaz de albergar distintos miembros, como, por ejemplo, métodos, capaces de actuar sobre el resto de miembros de la clase". ¿Es mía eh? Si piensas usar esta frase sabe que tengo todos los derechos sobre ella.

Pero, vamos a lo que vamos. De todo cuanto diga a partir de ahora (vale, y de lo que he dicho ya) me dejo corregir, que conste. Vamos a suponer que tienes una clase "Themes", que cuenta con una variable privada que albergará las "URLs" de determinadas hojas de estilo. ¿Me sigues? La clase "Themes" ¡cómo no! tendrá también un método público que permitirá al usuario de la misma añadir hojas de estilo, es decir, que, nosotros, privadamente, dentro de dicho método, añadiremos las URLsde las hojas de estilo en nuestra variable privada, que para eso la tenemos, para usarla, a ver qué te has pensado. Si te parece, vamos a ver esto con un poco de código fuente de PHP:

class Themes
{
  private $cssFiles;
 
  public function __construct(){
    $this->cssFiles = array();
  }
 
  public function AddCssFile($url){
    if(!in_array($url, $this->cssFiles)){
      $this->cssFiles[] = $url;
    }
  }
 
  public function PrintCss(){
    foreach($this->cssFiles as $cssFile){
      printf('', $cssFile);  
    }
  }
}

Ahí tenemos a nuestra amigo la clase "Themes". ¿Verdad que es chula? Tiene todo lo que le podemos pedir. ¡Pero qué digo! Tenemos más aún de lo que decía al principio, porque hemos añadido, para tratar de explicarme mejor, un método público capaz de imprimir las hojas de estilo de nuestra clase "Themes", es decir, la correspondiente etiqueta HTML para incluir las hojas de estilo dentro de un documento HTML. ¿Me sigues verdad?

Pensando un poco, o un mucho, ahora no importa, podemos llegar a la conclusión de que nos falta algo en nuestra clase "Themes", entre otras cosas, desde luego, que no damos opción a las hojas de estilo sino a ser del tipo "screen". ¿Qué pasa si queremos añadir una hoja de estilo para cuando nuestro documento HTML sea impreso por el usuario? Tal como están las cosas en la clase "Themes", eso ahora mismo es imposible.

Ahora bien, en un primer momento podemos concluir lo siguiente:

class Themes
{
  private $cssFiles;
 
  public function __construct(){
    $this->cssFiles = array();
  }
 
  public function AddCssFile($url, $media){
    if(!in_array($url, $this->cssFiles)){
      $this->cssFiles['url'] = $url;
      $this->cssFiles['url']['media'] = $media;
    }
  }
 
  public function PrintCss(){
    foreach($this->cssFiles as $url => $media){
      printf('', 
        $cssFile, $media);  
    }
  }
}

Podría funcionar, excepto que hemos tenido que hacer cambios significativos en la clase "Themes". Para empezar, hemos añadido un nuevo argumento al método "AddCssFile()". Hemos tenido también que hacer cambios al añadir las hojas de estilo, complicando un tanto nuestro miembro privado, la variable "Array" que almacena la información correspondiente. Y, por último, también hemos tenido que cambiar el método "PrintCSS()", para adaptarlo a las necesidades.

Ahora supón que mañana queremos añadir un nuevo argumento en la etiqueta HTML que incluirá la correspondiente hoja de estilo. ¿Añadimos otro nuevo argumento en el método "AddCssFile()"? ¿Y así hasta cuántos? ¿Y hacemos también el resto de cambios en consecuencia a la clase Themes? Ahora bien, ya que estoy preguntón: ¿qué tal si ahora nos ponemos un poco serios y utilizamos una nueva clase? Dos clases juntas no pueden sino traer cosas buenas. ¿Quieres ver cómo nos facilitaría la vida?

class CssFile
{
  private $url;
  private $media;
 
  const CSSFILE_MEDIA_SCREEN = 'screen';
 
  public function __construct($url, 
    $media = self::CSSFILE_MEDIA_SCREEN){
    $this->url = $url;
    $this->media = $media;
  }
}

Ya tenemos nuestra clase "CssFile" ahí, dispuesta a echarnos una mano. Representa a una hoja de estilo, desde luego, mejor que la URL por sí sola puede hacerlo. De este modo, la clase "Themes" podría contar con, en lugar de URLs de hojas de estilo, con una especie de hojas de estilo "concretas", representadas cada una de ellas por la clase "CssFile", que además puede contar con métodos útiles relacionados.

Con la URL no podemos hacer nada, sino usarla, con la clase "CssFile" podemos hacer más cosas, y ella misma puede hacer "cosas" por su cuenta además. ¿Cómo? ¿Que no terminas de verlo claro? Vamos a modificar nuestra clase "Themes" de modo que sea capaz de trabajar con nuestra nueva clase "CssFile", vas a ver:

class Themes
{
  private $cssFiles;
 
  public function __construct(){
    $this->cssFiles = array();
  }
 
  public function AddCssFile($cssFile){
    if($cssFile instanceof CssFile){
      $this->cssFiles[] = $cssFile;
    }
  }
 
  public function PrintCss(){
    foreach($this->cssFiles as $cssFile){
      $cssFile->PrintHtml();
    }
  }
}

¿Te das cuenta? Nuestra clase "Themes" no sólo se ha visto "reducida", sino que a mí me parece hasta más elegante. Pero, supón ahora que hiciera falta añadir más datos acerca de una hoja de estilo: estos vendrían ya dados en el único argumento del método "AddCssFile()", en el cual no tendremos necesidad de hacer cambio alguno. Pero tampoco tendremos que hacer cambios en el método "PrintCss()", que además ya no se encarga de la tarea de imprimir el código HTML necesario.

Efectivamente, ¿por qué no dejar esa tarea a la clase "CssFiles" que puede hacerlo perfectamente? Mira sino:

class CssFile
{
  private $url;
  private $media;
 
  const CSSFILE_MEDIA_SCREEN = 'screen';
 
  public function __construct($url, 
    $media = self::CSSFILE_MEDIA_SCREEN){
    $this->url = $url;
    $this->media = $media;
  }
 
  public function PrintHtml(){
    printf('', 
      $this->url, $this->media);  	  
  }
}

Y de este modo podríamos ir completando nuestra clase "CssFile", añadiendo algunos métodos útiles, como los conocidos "setter" and "getter", para mediar con nuestras variables miembros privadas. Pero, en todo caso, utilizar la clase "CssFile" nos puede ahorrar mucho trabajo, en mi opinión, clarifica el código fuente, previene el exceso de argumentos en un sólo método, etc., etc.

A mí me gustaría quedarme con el concepto de que es mejor lidiar con un tipo de dato complejo, y mucho mejor aún si este es un objeto, que no con tipos de datos simples, puesto que los primeros representan mucho mejor aquello que contienen. Claro que nada es perfecto, y también serían necesarios cambios en la clase "CssFile" de mi ejemplo, en caso de que se quisieran añadir más atributos a la etiqueta HTML de marras.

Pero no se puede negar que serían cambios más "señalizados", por decirlo así, contenidos dentro de la propia clase "CssFile", y así la clase "Themes" no habría de sufrir cambio alguno: recibiría lo mismo, y daría salida a lo mismo en cualquier caso. Recuerda también lo poco agradables que resultaban los cambios que había que hacer en la clase "Themes", ese "Array asociativo" que sólo podría complicarse más cada vez.

Y, en fin, no sé si te servirá de algo o qué, pero, esto es todo lo que tenía que decir, porque me parece que ya no me quedo nada en el tintero. Es muy posible que esté equivocado, o que no vea determinadas cuestiones como es menester, y si es así te agradecería que me lo hicieras saber dejando un comentario a esta entrada. Por mi parte, si he conseguido explicar más o menos (vale, mejor más que menos) la idea que me rondaba por la cabeza, y si esta no es demasiado estúpida, me doy por satisfecho.