Finales distintos
Los componentes y las interfaces tienen mecanismos de destrucción diferentes. Los componentes tienen un mecanismo de destrucción automático basado en el dueño (Owner) Las interfaces tienen un mecanismo de destrucción automático basado en la cantidad de referencias vigentes.Componentes
Cuando creamos un componente (una instancia de la clase TComponent o descendiente) el constructor recibe un parámetro de entrada de tipo TComponent. Si le pasamos nil entonces tendremos que encargarnos de destruir la instancia creada. Si le pasamos un objeto entonces cuando dicho objeto sea destruido se encargará de destruir las instancias de todos los objetos de los cuales es el dueño.procedure TMiForm.DoMiComponente;
var
oMiComponente: TMiComponente;
begin
oMiComponente := TMiComponente.Create(Self);
oMiComponente.Free;
end;
En el código anterior se crea una instancia de la clase TMiComponente y se mantiene una referencia a dicha instancia en la variable oMiComponente. Luego, a través de la referencia mantenida en dicha variable, se destruye la instancia. Como el Owner de la instancia de TMiComponente es Self, es decir, la instancia de TMiForm, si no destruyéramos explícitamente la instancia de TMiComponente, ésta sería destruída implícitamente al destruir la instancia de TMiForm.
Interfaces
Cuando creamos una instancia de una clase que implementa una interface y obtenemos referencias a la interface, internamente se lleva la cuenta de la cantidad de referencias vigentes. Cuando dicha cantidad llega a 0, es decir, ya no hay referencias vigentes, la instancia de la clase puede ser destruida. El código responsable de hacerlo es insertado automáticamente por el compilador y no tenemos ningún control sobre el mismo.procedure TMiForm.DoMiInterface;
var
oMiInterface: IMiInterface;
begin
oMiInterface := TMiInterface.Create as IMiInterface;
oMiInterface := nil;
end;
En el código anterior se crea una instancia de la clase TMiInterface que implementa la interface IMiInterface y se obtiene una referencia a dicha interface que se mantiene en la variable oMiInterface. Cuando dicha referencia deja de estar vigente, en este caso al asignarle nil, la instancia será destruida por el código insertado por el compilador. Si no le asignáramos nil a la variable oMiInterface, la referencia dejaría de estar vigente al finalizar la ejecución del método DoMiInterface porque la variable es local para dicho método.
Un ejemplo
Veamos un ejemplo muy simple.type
IMiInterface = interface(IInterface)
['{F0E8209C-4D47-46C5-B28F-D19ACEEC9552}']
procedure DoMiMetodo;
end;
TMiObjeto = class(TInterfacedObject, IMiInterface)
{ IMiInterface }
protected
procedure DoMiMetodo;
{ IMiInterface }
public
destructor Destroy; override;
end;
TfrmMiForm = class(TForm)
btnMiMetodo: TButton;
procedure btnMiMetodoClick(Sender: TObject);
end;
En la sección Interface, primero declaramos la interface, luego la clase que implementa la interface y finalmente el Form (la parte del Form la hace Delphi)
{ TfrmMiForm }
procedure TfrmMiForm.btnMiMetodoClick(Sender: TObject);
begin
(TMiObjeto.Create as IMiInterface).DoMiMetodo;
end;
{ TMiObjeto }
destructor TMiObjeto.Destroy;
begin
inherited;
end;
procedure TMiObjeto.DoMiMetodo;
begin
ShowMessage('MiMetodo');
end;
En la sección Implementation implementamos los métodos. La implementación del método Destroy es sólo para poner un breakpoint y ver cómo el código insertado por el compilador destruye la instancia de TMiObjeto.
TInterfacedObject
Para que todo esto sea posible es necesario que la clase que implementa la interface descienda de la clase TInterfacedObject, que es donde se implementa el mecanismo de destrucción automático basado en la cantidad de referencias vigentes.Descargar proyecto Delphi 2010