15 - Clases abstractas y concretas.


Una clase abstracta tiene por objetivo agrupar atributos y métodos que luego serán heredados por otras subclases.

En conceptos anteriores planteamos las tres clase: Operacion, Suma y Resta. Vimos que no tenía sentido definir objetos de la clase Operacion (clase abstracta) y si definimos objetos de las clases Suma y Resta (clases concretas).

No es obligatorio que toda clase padre sea abstracta. Podemos tener por ejemplo un problema donde tengamos una clase padre (superclase) llamada Persona y una subclase llamada Empleado y luego necesitemos definir objetos tanto de la clase Persona como de la clase Empleado.

Existe una sintaxis en PHP para indicar que una clase es abstracta:

abstract class [nombre de clase] {
  [atributos]
  [metodos]
}

La ventaja de definir las clases abstractas con este modificador es que se producirá un error en tiempo de ejecución si queremos definir un objeto de dicha clase. Luego hay que tener bien en cuenta que solo podemos definir objetos de las clases concretas.

Luego el problema de herencia de las clases Operacion, Suma y Resta es:

<html>
<head>
<title>Pruebas</title>
</head>
<body>
<?php
abstract class Operacion {
  protected $valor1;
  protected $valor2;
  protected $resultado;
  public function cargar1($v)
  {
    $this->valor1=$v;
  }
  public function cargar2($v)
  {
    $this->valor2=$v;
  }
  public function imprimirResultado()
  {
    echo $this->resultado.'<br>';
  }
}

class Suma extends Operacion{
  public function operar()
  {
    $this->resultado=$this->valor1+$this->valor2;
  }
}

class Resta extends Operacion{
  public function operar()
  {
    $this->resultado=$this->valor1-$this->valor2;
  }
}

$suma=new Suma();
$suma->cargar1(10);
$suma->cargar2(10);
$suma->operar();
echo 'El resultado de la suma de 10+10 es:';
$suma->imprimirResultado();

$resta=new Resta();
$resta->cargar1(10);
$resta->cargar2(5);
$resta->operar();
echo 'El resultado de la diferencia de 10-5 es:';
$resta->imprimirResultado();
?>
</body>
</html> 

El único cambio que hemos producido a nuestro ejemplo está en la línea donde declaramos la clase Operacion:

abstract class Operacion {

No varía en nada la declaración de las otras dos clases:

class Suma extends Operacion{
...
}

class Resta extends Operacion{
...
}

Es decir que las clases concretas son aquellas que no le antecedemos el modificador abstract.

La definición de objetos de la clase Suma y Resta no varía:

$suma=new Suma();
$suma->cargar1(10);
$suma->cargar2(10);
$suma->operar();
echo 'El resultado de la suma de 10+10 es:';
$suma->imprimirResultado();

$resta=new Resta();
$resta->cargar1(10);
$resta->cargar2(5);
$resta->operar();
echo 'El resultado de la diferencia de 10-5 es:';
$resta->imprimirResultado();

Ahora bien si tratamos de definir un objeto de la clase Operación:

$operacion1=new Operacion();
$operacion1->cargar1(12);
$operacion1->cargar2(6);
$operacion1->imprimirResultado();

Se produce un error:

Fatal error: Cannot instantiate abstract class Operacion 

Es decir que luego cuando utilicemos las clases que desarrollamos (definamos objetos) solo nos interesan las clases concretas.

Retornar