La herencia en PHP 5, Segunda parte

  • Por
Continuamos con los mecanismos de herencia en PHP5. Creamos clases que heredan de otra clase y aprendemos a sobrescribir métodos.

Como estamos viendo, los mecanismos de herencia en PHP5 son similares a los existentes en otros lenguajes de programación. Ahora vamos a relatar cómo construir una clase que hereda de otra.

Continuando con nuestro ejemplo de videoclub, vamos a construir una clase para los soportes de tipo cinta de video. Las cintas de vídeo tienen un atributo nuevo que es la duración de la cinta. No tienen ninguna clase nueva, aunque debemos aprender a sobrescribir métodos creados para el soporte, dado que ahora tienen que hacer tareas más específicas.

Sobrescribir métodos

Antes de mostrar el código de la clase cinta_video, vamos a hablar sobre la sobrescritura o sustitución de métodos, que es un mecanismo por el cual una clase que hereda puede redefinir los métodos que está heredando.

Pensemos en una cafetera. Sabemos que existen muchos tipos de cafeteras y todas hacen café, pero el mecanismo para hacer el café es distinto dependiendo del tipo de cafetera. Existen cafeteras express, cafeteras por goteo y hasta se puede hacer café con un calcetín. Nuestra cafetera "padre" (de la que va a heredar todas las cafeteras) puede tener definido un método hacer_cafe(), pero no necesariamente todas las cafeteras que puedan heredar de esta hacen el café siguiendo el mismo proceso.

Entonces podemos definir un método para hacer café estándar, que tendría la clase cafetera. Pero al definir las clases cafetera_express y cafetera_goteo, deberíamos sobrescribir el método hacer_cafe() para que se ajuste al procedimiento propio de estas.

La sobrescritura de métodos es algo bastante común en mecanismos de herencia, puesto que los métodos que fueron creados para una clase "padre" no tienen por qué ser los mismos que los definidos en las clases que heredan.

Veremos cómo sobrescribir o sustituir métodos en un ejemplo de herencia, siguiendo nuestro ejemplo de videoclub.

Sintaxis para heredar en PHP 5

Habíamos comentado que el videoclub dispone de distintos elementos para alquilar, como cintas de vídeo, DVD o juegos. Habíamos creado una clase soporte, que vamos a heredar en cada uno de los elementos disponibles para alquiler. Vamos a empezar por la clase cinta_video, cuyo código será el siguiente.

class cinta_video extends soporte{ 
   private $duracion; 

   function __construct($tit,$num,$precio,$duracion){ 
      parent::__construct($tit,$num,$precio); 
      $this->duracion = $duracion; 
   } 

   public function imprime_caracteristicas(){ 
      echo "Película en VHS:<br>"; 
      parent::imprime_caracteristicas(); 
      echo "<br>Duración: " . $this->duracion; 
   } 
}

Con la primera línea class cinta_video extends soporte estamos indicando que se está definiendo la clase cinta_video y que va a heredar de la clase soporte.

Nota: Como se está heredando de una clase, PHP tiene que conocer el código de la clase "padre", en este caso la clase soporte. De modo que el código de la clase soporte debe estar incluido dentro del archivo de la clase cinta_video. Podemos colocar los dos códigos en el mismo fichero, o si están en ficheros independientes, debemos incluir el código de la clase soporte con la instrucción include o require de PHP.

En la clase cinta_video hemos definido un nuevo atributo llamado $duracion, que almacena el tiempo que dura la película.

Aunque la clase sobre la que heredamos (la clase soporte) tenía definido un constructor, la cinta de vídeo debe inicializar la nueva propiedad $duracion, que es específica de las cintas de video. Por ello, vamos a sobrescribir o sustituir el método constructor, lo que se hace simplemente volviendo a escribir el método. La gracia aquí consiste en que el sistema puede basar la nueva declaración del constructor en la declaración que existía para la clase de la que hereda.

Es decir, ya se había definido un constructor para la clase soporte, que inicializaba los atributos de esta clase. Ahora, para la clase cinta_video, hay que inicializar los atributos definidos en la clase soporte, más el atributo $duracion, que es propio de cinta_video.

El código del constructor es el siguiente:

function __construct($tit,$num,$precio,$duracion){ 
   parent::__construct($tit,$num,$precio); 
   $this->duracion = $duracion; 
}

En la primera línea del constructor se llama al constructor creado para la clase "soporte". Para ello utilizamos parent:: y luego el nombre del método de la clase padre al que se quiere llamar, en este caso __constructor(). Al constructor de la clase padre le enviamos las variables que se deben inicializar con la clase padre.

En la segunda línea del constructor se inicializa el atributo duracion, con lo que hayamos recibido por parámetro.

Nos pasa lo mismo con el método imprime_caracteristicas(), que ahora debe mostrar también el nuevo atributo, propio de la clase cinta_video. Como se puede observar en el código de la función, se hace uso también de parent::imprime_caracteristicas() para utilizar el método definido en la clase padre.

Si queremos probar la clase cinta_video, podriamos utilizar un código como este:

$micinta = new cinta_video("Los Otros", 22, 4.5, "115 minutos"); 
echo "<b>" . $micinta->titulo . "</b>"; 
echo "<br>Precio: " . $micinta->dame_precio_sin_iva() . " euros"; 
echo "<br>Precio IVA incluido: " . $micinta->dame_precio_con_iva() . " euros";

Lo que nos devolvería lo siguiente:

Los Otros
Precio: 4.5 euros
Precio IVA incluido: 5.22 euros
Película en VHS:
Los Otros
4.5 (IVA no incluido)
Duración: 115 minutos

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Santiago

01/3/2006
Alguien probo este codigo? No devuelve lo que dice ahi, sino que solo da
Los Otros
Precio: 4.5 euros
Precio IVA incluido: 5.22 euros
lo del vhs ni noticias.

Alfredo

17/7/2006
En efecto no devuelve el resultado expuesto en el articulo, ya que le falto implementar la funcion imprime_caracteristicas( ); .. yo probé agregando la funcion.

Manumene

07/9/2007
Yo lo q no entiendo es lo de public o private...por q no se ponen todas public, y ya no hacen falta las funciones de dame_precio y eso....

Ricardo

10/8/2009
Encapsulación
Manumene, lo que pasa es que si recuerdas uno de los paradigmas de la programación orientada a objetos es la "Encapsulación", o sea la protección de los datos, esto se hace para que en programas con cierto grado de complejidad sea más difícil que el programador pueda insertar errores al momento de codificar, que se altere alguna variable en vez de otra, etc.

Lina Fernanda Ramirez

15/10/2009
felicitarlo
mejor explicado no pudo estar, entendi perfectamente los temas que necesitaba, muchas gracias....

Luna

20/11/2009
Sobre metodos
Hay q tener en cuenta que sobreescritura de un metodo , una es cuando varia en el nro de parametros, el tipo de valor retornado, aca estamos hablando de metodos sobrecargados. Lo otro es cuando un metodo, no se modifica en nada el nro de paramentros, y aveces ni en el tipo de valor retornado, lo unico que modifica es su contenido, el cual adaptamos a las necesidades tal como el ejemplo q cita el autor en este articulo imprime caracteristicas. Solo queria hacer la aclaracion.

harryson_gonzalez

27/11/2009
sobre lo q dijo luna
ps luna yo creo q lodel autor esta bn, por q la otra ves hice un programita en java
, usando herencia(poo), lo cual se hace es por super y no por parent(hace lo mismo)

a lo q me lleva a decirte q es necesario. ¿como tu dices q de cierta manera se esta sobrecargando un metodo constructor padre?, pero dime si tu quisieras agregar un atributo a una clase hijo de q manera lo harias

asi q no se esta sobrecargando el metodo q quede claro, simplemete se esta agregando su constructor correspondiente y hay es q se puede llamar al constructor padre

edujmb

15/2/2010
La herencia en PHP 5
Magnífico el artículo, felicitaciones.

Jam

16/1/2011
falta una linea de codigo
Excelente el articulo,
pero falta una linea de codigo en el ultimo script para que salga como dices:

echo "<br>".$micinta->imprime_caracteristicas();


MUchas gracias.

osiris_lor

16/7/2011
Duda con la extended
Saludos a la banda antes que nada.
A ver si me pueden hechar la mano.
Creen se puede hacer lo siguiente?
class miclase extended otraclase extended otraclasemas
{
..
..
..
}

Si es posible super, creo que podre hacer varias cosas, pero si no se puede, alguna idea de que hacer para combinar mas de una clase
Gracias anticipadas.

Isaak

12/12/2015
insertar en herencia
y al reves??? para insertar se puede???