delphi interface delphi-2007 implements

Implementos de interfaz Delphi



interface delphi-2007 (1)

Lo que sucede aquí es que llamas a TContainer.Create y creas una instancia a un objeto. Pero luego asigna esa instancia a una referencia de interfaz, la variable global Foo . Como esa variable es de tipo IFoo , la delegación de interfaz significa que el objeto de implementación es la instancia de TFooImpl y no la instancia de TContainer .

Por lo tanto, nada toma nunca una referencia a la instancia de TContainer , su recuento de referencia nunca se incrementa, por lo que nunca se destruye.

No creo que haya una manera muy fácil de evitar esto. Es posible que pueda usar TAggregatedObject pero puede que no resuelva su problema. Te obligaría a declarar que TContainer.FFoo es del tipo TFooImpl lo que imagino que no quieres hacer. De todos modos, esto es lo que parece ser refundido de esa manera:

program SO16210993_TAggregatedObject; {$APPTYPE CONSOLE} type IFoo = interface procedure Foo; end; TFooImpl = class(TAggregatedObject, IFoo) procedure Foo; end; TContainer = class(TInterfacedObject, IFoo) private FFoo: TFooImpl; function GetFoo: IFoo; public destructor Destroy; override; property Foo: IFoo read GetFoo implements IFoo; end; procedure TFooImpl.Foo; begin Writeln(''TFooImpl.Foo called''); end; destructor TContainer.Destroy; begin Writeln(''TContainer.Destroy called'');//this line does run FFoo.Free; inherited; end; function TContainer.GetFoo: IFoo; begin if not Assigned(FFoo) then FFoo := TFooImpl.Create(Self); Result := FFoo; end; procedure Main; var Foo : IFoo; begin Foo := TContainer.Create; Foo.Foo; end; begin Main; Readln; end.

La documentación habla de esto:

La clase que use para implementar la interfaz delegada debería derivarse de TAggregationObject.

Inicialmente no pude encontrar ninguna documentación para este TAggregationObject . Y finalmente me di cuenta de que en realidad se llama TAggregatedObject y está documentado .

TAggregatedObject proporciona la funcionalidad para un objeto interno de un agregado mediante la implementación de los métodos de interfaz IInterface para delegar en la interfaz de control.

Un objeto agregado es un objeto compuesto por varios objetos interconectados. Cada objeto implementa su propio comportamiento e interfaces, pero todos los objetos comparten el mismo recuento de referencia, que es el del objeto controlador. En el patrón de contenedor, el controlador es el objeto contenedor.

TAggregatedObject no admite ninguna interfaz por sí mismo. Sin embargo, como es típico de un agregado, sí implementa los métodos de IInterface, que son utilizados por los objetos que descienden de él. TAggregatedObject, por lo tanto, sirve como base para las clases que implementan interfaces para crear objetos que son parte de un agregado.

TAggregatedObject se usa como base para clases que crean objetos contenidos y objetos de conexión. El uso de TAggregatedObject garantiza que las llamadas a los métodos de interfaz indirecta deleguen en la interfaz de control del agregado.

La interfaz de control II se especifica en el constructor de TAggregatedObject y se indica mediante la propiedad Controller.

Además, está esto de los comentarios del código fuente:

TAggregatedObject y TContainedObject son clases base adecuadas para objetos interconectados destinados a ser agregados o contenidos en un objeto de control externo. Al utilizar la sintaxis "implementa" en una propiedad de interfaz en una declaración de clase de objeto externa, utilice estos tipos para implementar el objeto interno.

Las interfaces implementadas por objetos agregados en nombre del controlador no deben distinguirse de otras interfaces proporcionadas por el controlador. Los objetos agregados no deben mantener su propia cuenta de referencia; deben tener la misma duración que su controlador. Para lograr esto, los objetos agregados reflejan los métodos de conteo de referencia para el controlador.

TAggregatedObject simplemente refleja las llamadas QueryInterface a su controlador. A partir de dicho objeto agregado, se puede obtener cualquier interfaz compatible con el controlador, y solo las interfaces que admite el controlador. Esto es útil para implementar una clase de controlador que use uno o más objetos internos para implementar las interfaces declaradas en la clase de controlador. La agregación promueve la distribución de la implementación a través de la jerarquía de objetos.

TAggregatedObject es de lo que la mayoría de los objetos agregados deben heredar, especialmente cuando se utiliza junto con la sintaxis "implementa".

Esperaría que el recuento de referencias funcione en el objeto agregado externo en una implementación de interfaz. Si puedo referirme a otro ejemplo: claridad en las clases que implementan múltiples interfaces (alternativa a la delegación):

Aquí hay una reproducción mínima del comportamiento:

program SO16210993; {$APPTYPE CONSOLE} type IFoo = interface procedure Foo; end; TFooImpl = class(TInterfacedObject, IFoo) procedure Foo; end; TContainer = class(TInterfacedObject, IFoo) private FFoo: IFoo; public constructor Create; destructor Destroy; override; property Foo: IFoo read FFoo implements IFoo; end; procedure TFooImpl.Foo; begin Writeln(''TFooImpl.Foo called''); end; constructor TContainer.Create; begin inherited; FFoo := TFooImpl.Create; end; destructor TContainer.Destroy; begin Writeln(''TContainer.Destroy called'');//this line never runs inherited; end; procedure Main; var Foo : IFoo; begin Foo := TContainer.Create; Foo.Foo; end; begin Main; Readln; end.

Si en lugar de usar implements , implemento la interfaz en la clase TImplementor , se ejecuta el destructor.