7 - Modificadores de acceso a atributos y métodos (public - private)


Hasta ahora hemos dicho que los atributos conviene definirlos con el modificador private y los métodos los hemos estado haciendo a todos public.

Analisemos que implica disponer un atributo privado (private), en el concepto anterior definíamos dos atributos para almacenar la cantidad de filas y columnas en la clase Tabla:

  private $cantFilas;
  private $cantColumnas;

Al ser privados desde fuera de la clase no podemos modificarlos:

$tabla1->cantFilas=20;

El resultado de ejecutar esta línea provoca el siguiente error:

Fatal error: Cannot access private property Tabla::$cantFilas

No olvidemos entonces que los atributos los modificamos llamando a un método de la clase que se encarga de inicializarlos (en la clase Tabla se inicializan en el constructor):

$tabla1=new Tabla(2,3);

Ahora vamos a extender este concepto de modificador de acceso a los métodos de la clase. Veíamos hasta ahora que todos los métodos planteados de la clase han sido públicos. Pero en muchas situaciones conviene que haya métodos privados (private).

Un método privado (private) solo puede ser llamado desde otro método de la clase. No podemos llamar a un método privados desde donde definimos un objeto.

Con la definición de métodos privados se elimina la posibilidad de llamar a métodos por error, consideremos el problema del concepto anterior (clase Tabla) donde creamos un objeto de dicha clase y llamamos por error al método finTabla:

$tabla1=new Tabla(2,3);
$tabla1->finTabla();
$tabla1->cargar(1,1,"1");
$tabla1->cargar(1,2,"2");
$tabla1->cargar(1,3,"3");
$tabla1->cargar(2,1,"4");
$tabla1->cargar(2,2,"5");
$tabla1->cargar(2,3,"6");
$tabla1->graficar();

Este código produce un error lógico ya que al llamar al método finTabla() se incorpora al archivo HTML la marca </html>.

Este tipo de error lo podemos evitar definiendo el método finTabla() con modificador de acceso private:

  private function finTabla()
  {
    echo '</table>';
  }

Luego si volvemos a ejecutar:

$tabla1=new Tabla(2,3);
$tabla1->finTabla();
$tabla1->cargar(1,1,"1");
...

Se produce un error sintáctico:

Fatal error: Call to private method Tabla::finTabla()

Entonces el modificador private nos permite ocultar en la clase atributos y métodos que no queremos que los accedan directamente quien definen objetos de dicha clase. Los métodos públicos es aquello que queremos que conozcan perfectamente las personas que hagan uso de nuestra clase (también llamada interfaz de la clase)

Nuestra clase Tabla ahora correctamente codificada con los modificadores de acceso queda:

<html>
<head>
<title>Pruebas</title>
</head>
<body>
<?php
class Tabla {
  private $mat=array();
  private $cantFilas;
  private $cantColumnas;
  public function __construct($fi,$co)
  {
    $this->cantFilas=$fi;
    $this->cantColumnas=$co;
  }
  
  public function cargar($fila,$columna,$valor)
  {
    $this->mat[$fila][$columna]=$valor;
  }

  private function inicioTabla()
  {
    echo '<table border="1">';
  }

  private function inicioFila()
  {
    echo '<tr>';
  }
  
  private function mostrar($fi,$co)
  {
    echo '<td>'.$this->mat[$fi][$co].'</td>';
  }

  private function finFila()
  {
    echo '</tr>';
  }

  private function finTabla()
  {
    echo '</table>';
  }

  public function graficar()
  {
    $this->inicioTabla();
    for($f=1;$f<=$this->cantFilas;$f++)
    {
      $this->inicioFila();
      for($c=1;$c<=$this->cantColumnas;$c++)
      {
        $this->mostrar($f,$c);
      } 
      $this->finFila();
    }
    $this->finTabla();
  }
}

$tabla1=new Tabla(2,3);
$tabla1->cargar(1,1,"1");
$tabla1->cargar(1,2,"2");
$tabla1->cargar(1,3,"3");
$tabla1->cargar(2,1,"4");
$tabla1->cargar(2,2,"5");
$tabla1->cargar(2,3,"6");
$tabla1->graficar();
?>
</body>
</html>

Tenemos tres métodos públicos:

  public function __construct($fi,$co)
  public function cargar($fila,$columna,$valor)
  public function graficar()

Y cinco métodos privados:

  private function inicioTabla()
  private function inicioFila()
  private function mostrar($fi,$co)
  private function finFila()
  private function finTabla()

Tengamos en cuenta que cuando definimos un objeto de la clase Tabla solo podemos llamar a los métodos públicos. Cuando documentamos una clase debemos hacer mucho énfasis en la descripción de los métodos públicos, que serán en definitiva los que deben llamarse cuando definamos objetos de dicha clase.

Uno de los objetivos fundamentales de la POO es el encapsulamiento. El encapsulamiento es una técnica por el que se ocultan las características internas de una clase de todos aquellos elementos (atributos y métodos) que no tienen porque conocerla otros objetos. Gracias al modificador private podemos ocultar las características internas de nuestra clase.

Cuando uno planea una clase debe poner mucha atención cuales responsabilidades (métodos) deben ser públicas y cuales responsabilidades no queremos que las conozcan los demás.

Retornar