8 - Colaboración de objetos.


Hasta ahora nuestros ejemplos han presentado una sola clase, de la cual hemos definido uno o varios objetos. Pero una aplicación real consta de muchas clases.

Veremos que hay dos formas de relacionar las clases. La primera y la que nos concentramos en este concepto es la de COLABORACIóN.

Cuando dentro de una clase definimos un atributo o una variable de otra clase decimos que esta segunda clase colabora con la primera. Cuando uno a trabajado por muchos años con la metodología de programación estructurada es difícil subdividir un problema en clases, tiende a querer plantear una única clase que resuelva todo.

Presentemos un problema:Una página web es común que contenga una cabecera, un cuerpo y un pié de página. Estas tres secciones podemos perfectamente identificarlas como clases. También podemos identificar otra clase pagina. Ahora bien como podemos relacionar estas cuatro clases (pagina, cabecera, cuerpo, pie), como podemos imaginar la cabecera, cuerpo y pie son partes de la pagina. Luego podemos plantear una clase pagina que contenga tres atributos de tipo objeto.

En forma simplificada este problema lo podemos plantear así:

class Cabecera {
  [atributos y métodos]
}
class Cuerpo {
  [atributos y métodos]
}
class Pie {
  [atributos y métodos]
}
class Pagina {
  private $cabecera;
  private $cuerpo;
  private $pie;
  [métodos] 
}

$pag=new Pagina();

Como podemos ver declaramos cuatro clases (Cabecera, Cuerpo, Pie y Pagina), fuera de cualquier clase definimos un objeto de la clase Pagina:

$pag=new Pagina();

Dentro de la clase Pagina definimos tres atributos de tipo objeto de las clases Cabecera, Cuerpo y Pie respectivamente. Luego seguramente dentro de la clase Pagina crearemos los tres objetos y llamaremos a sus métodos respectivos.

Veamos una implementación real de este problema:

<html>
<head>
<title>Pruebas</title>
</head>
<body>
<?php
class Cabecera {
  private $titulo;
  public function __construct($tit)
  {
    $this->titulo=$tit;
  }
  public function graficar()
  {
    echo '<h1 style="text-align:center">'.$this->titulo.'</h1>';
  }
}

class Cuerpo {
  private $lineas=array();
  public function insertarParrafo($li)
  {
    $this->lineas[]=$li;
  }
  public function graficar()
  {
    for($f=0;$f<count($this->lineas);$f++)
    {
      echo '<p>'.$this->lineas[$f].'</p>';
    }
  }
}

class Pie {
  private $titulo;
  public function __construct($tit)
  {
    $this->titulo=$tit;
  }
  public function graficar()
  {
    echo '<h4 style="text-align:left">'.$this->titulo.'</h4>';
  }
}

class Pagina {
  private $cabecera;
  private $cuerpo;
  private $pie;
  public function __construct($texto1,$texto2)
  {
    $this->cabecera=new Cabecera($texto1);
    $this->cuerpo=new Cuerpo();
    $this->pie=new Pie($texto2);
  }
  public function insertarCuerpo($texto)
  {
    $this->cuerpo->insertarParrafo($texto);
  }
  public function graficar()
  {
    $this->cabecera->graficar();
    $this->cuerpo->graficar();
    $this->pie->graficar();
  }
}

$pagina1=new Pagina('Título de la Página','Pie de la página');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 1');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 2');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 3');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 4');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 5');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 6');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 7');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 8');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 9');
$pagina1->graficar();
?>
</body>
</html>

La primer clase llamada Cabecera define un atributo llamada $titulo que se carga en el constructor, luego se define otro método que imprime el HTML:

class Cabecera {
  private $titulo;
  public function __construct($tit)
  {
    $this->titulo=$tit;
  }
  public function graficar()
  {
    echo '<h1 style="text-align:center">'.$this->titulo.'</h1>';
  }
}

La clase Pie es prácticamente idéntica a la clase Cabecera, solo que cuando genera el HTML lo hace con otro tamaño de texto y alineado a izquierda:

class Pie {
  private $titulo;
  public function __construct($tit)
  {
    $this->titulo=$tit;
  }
  public function graficar()
  {
    echo '<h4 style="text-align:left">'.$this->titulo.'</h4>';
  }
}

Ahora la clase Cuerpo define un atributo de tipo array donde se almacenan todos los párrafos. Esta clase no tiene constructor, sino un método llamado insertarParrafo que puede ser llamado tantas veces como párrafos tenga el cuerpo de la página. Esta actividad no la podríamos haber hecho en el constructor ya que el mismo puede ser llamado solo una vez.

Luego el código de la clase Cuerpo es:

class Cuerpo {
  private $lineas=array();
  public function insertarParrafo($li)
  {
    $this->lineas[]=$li;
  }
  public function graficar()
  {
    for($f=0;$f<count($this->lineas);$f++)
    {
      echo '<p>'.$this->lineas[$f].'</p>';
    }
  }
}

Para graficar todos los párrafos mediante una estructura repetitiva disponemos cada uno de los elementos del atributo $lineas dentro de las marcas <p> y </p>.

Ahora la clase que define como atributos objetos de la clase Cabecera, Cuerpo y Pie es la clase Pagina:

class Pagina {
  private $cabecera;
  private $cuerpo;
  private $pie;
  public function __construct($texto1,$texto2)
  {
    $this->cabecera=new Cabecera($texto1);
    $this->cuerpo=new Cuerpo();
    $this->pie=new Pie($texto2);
  }
  public function insertarCuerpo($texto)
  {
    $this->cuerpo->insertarParrafo($texto);
  }
  public function graficar()
  {
    $this->cabecera->graficar();
    $this->cuerpo->graficar();
    $this->pie->graficar();
  }
}

Al constructor llegan dos cadenas con las que inicializamos los atributos $cabecera y $pie:

    $this->cabecera=new Cabecera($texto1);
    $this->cuerpo=new Cuerpo();
    $this->pie=new Pie($texto2);

Al atributo $cuerpo también lo creamos pero no le pasamos datos ya que dicha clase no tiene constructor con parámetros.

La clase Pagina tiene un método llamado:

  public function insertarCuerpo($texto)

que tiene como objetivo llamar al método insertarParrafo del objeto $cuerpo.

El método graficar de la clase Pagina llama a los métodos graficar de los objetos Cabecera, Cuerpo y Pie en el orden adecuado:

  public function graficar()
  {
    $this->cabecera->graficar();
    $this->cuerpo->graficar();
    $this->pie->graficar();
  }

Finalmente hemos llegado a la parte del algoritmo donde se desencadena la creación del primer objeto, definimos un objeto llamado $pagina1 de la clase Pagina y le pasamos al constructor los textos a mostrar en la cabecera y pie de pagina, seguidamente llamamos al método insertarCuerpo tantas veces como información necesitemos incorporar a la parte central de la página. Finalizamos llamando al método graficar:

$pagina1=new Pagina('Título de la Página','Pie de la página');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 1');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 2');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 3');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 4');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 5');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 6');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 7');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 8');
$pagina1->insertarCuerpo('Esto es una prueba que debe aparecer dentro del cuerpo de la página 9');
$pagina1->graficar();

Retornar