15 octubre 2007

Implementando interfaces en Delphi (I)

Delphi es un lenguaje que utiliza la herencia simple al contrario de C++ que permite herencia múltiple. Esto significa que cualquier clase sólo puede heredar de una clase padre. Por lo tanto, si queremos que una clase herede métodos de más de una clase entonces hay que utilizar interfaces (interface).

Una interfaz es como una clase que contiene sólo métodos abstractos (métodos sin implentación) definiendo limpiamente su funcionalidad. Por convención, los nombres de las interfaces comienzan con la letra mayúscula I.

Veamos un ejemplo de definición de interfaz para un artículo:

type
IArticulo = interface
procedure IncrementarExistencias( rCantidad: Real );
procedure DecrementarExistencias( rCantidad: Real );
function Facturar: Integer;
end;

Las interfaces nunca pueden ser instanciadas. Es decir, no se puede hacer:

var
Articulo: IArticulo;
begin
Articulo := IArticulo.Create;
end;

Al compilar nos daría el error:

Object or class typed required (se requiere una clase u objeto)

Para utilizar una interfaz necesitamos implementarla a través de una clase. Se haría de la siguiente manera:

type
TArticulo = class( TInterfacedObject, IArticulo )
procedure IncrementarExistencias( rCantidad: Real );
procedure DecrementarExistencias( rCantidad: Real );
function Facturar: Integer;

¿Que ventajas aporta esto respecto a una clase abstracta? Pues en este caso la definición es más limpia, nada más. Ahora veremos que ventaja de utilizar interfaces.

UTILIZANDO EL POLIMORFIRMO PARA LA CREACION DE CLASES

Las clases polimórficas son aquellas clases que teniendo una definición común se pueden utilizar para distintos tipos de objeto. Supongamos que tenemos la siguiente interfaz:

IVehiculo = interface
procedure Matricular;
end;

Utilizando la misma interfaz vamos a definir una clase para cada tipo de vehículo:

type
TCoche = class( TInterfacedObject, IVehiculo )
procedure Matricular;
end;

TCamion = class( TInterfacedObject, IVehiculo )
procedure Matricular;
end;

Ahora instanciamos ambas clases utilizando la misma interfaz:

var
Vehiculo: IVehiculo;
begin
Vehiculo := TCoche.Create;
Vehiculo.Matricular;
Vehiculo := TCamion.Create;
Vehiculo.Matricular;
end;

En este caso todas las clases que implementan la interfaz IVehiculo tienen un método común pero podría darse el caso de que tuvieran métodos distintos, lo cual significa que hay que utilizar la herencia múltiple.

UTILIZANDO HERENCIA MULTIPLE MEDIANTE INTERFACES

Supongamos que tenemos estas dos interfaces:

type
IVehiculo = interface
procedure Matricular;
end;

IRemolque = interface
procedure Cargar;
end;

El vehículo tiene el método Matricular y el remolque tiene el método Cargar. A mi me interesa que un coche utilice el método Matricular, pero sólo el camión tiene que poder Cargar. Entonces la implementación de las clases de haría así:

TCoche = class( TInterfacedObject, IVehiculo )
procedure Matricular;
end;

TCamion = class( TInterfacedObject, IVehiculo, IRemolque )
procedure Matricular;
procedure Cargar;
end;

Como puede apreciarse la clase TCoche sólo implementa la interfaz IVehiculo pero la clase TCamion hereda implementa simultáneamente las interfaces IVehiculo y IRemolque pudiendo utilizar sus métodos indistintamente. Esto es lo que se conoce como herencia múltiple.

En el próximo artículo seguiremos viendo más características sobre las interfaces.

Pruebas realizadas en Delphi 7.

Publicidad