Há um recurso muito interessante no Object Pascal que é a classe aninhada - nested classes em inglês. É um recurso existente em Java e .NET a tempos.
A grosso modo permite você implementar uma classe dentro de outra. O ganho disso é você conseguir elaborar uma classe "auto-suficiente", protegendo - se for este o caso - as soluções que você desenvolveu.
Bom, indo ao ponto. Desenvolvi a unit abaixo exemplificando a implementação de uma classe aninhada. Para efeitos didáticos o objetivo do programa é o seguinte:
Implementar um liberador de objetos.
Para isso, desenvolvi a classe TLiberador que é descendente de TObject. Ela implementa, então, a classe TLiberadorThread que por sua vez descende de TThread.
Logo, TLiberadorThread só é visível pela classe TLiberador e é isso que é o pulo do gato.
Compartilho da opinião que a legibilidade do código fica inicialmente comprometida mas creio ser uma questão de adaptação.
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, SyncObjs, Contnrs, ComCtrls, Unt_MemoryMonitor,
Unt_RotinasLog;
type
{
Classe responsável por liberar objetos
}
TLiberador = class(TObject)
strict private type {<== Declaração de tipo dentro da classe!}
TLiberadorThread = class(TThread)
strict private
FQueue: TObjectQueue;
FCritical: TCriticalSection;
procedure WhenTerminate(Sender: TObject);
protected
procedure Execute; override;
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
procedure AddObject(poObject: TObject);
end;
strict private
FDetail: TLiberadorThread; {<== Instância da classe aninhadaS}
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
procedure AddObject(poObject: TObject);
end;
{
Formulário com um botão que adiciona um objeto na pilha
}
TForm2 = class(TForm)
Button1: TButton;
g4MemoryMonitor1: Tg4MemoryMonitor;
StatusBar1: TStatusBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
FTeste: TLiberador;
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
{ TLiberador.TLiberadorThread }
procedure TLiberador.TLiberadorThread.AddObject(poObject: TObject);
begin
Self.FCritical.Enter;
try
Self.FQueue.Push(poObject);
finally
Self.FCritical.Release;
end;
end;
procedure TLiberador.TLiberadorThread.AfterConstruction;
begin
inherited;
Self.OnTerminate := Self.WhenTerminate;
Self.FQueue := TObjectQueue.Create;
Self.FCritical := TCriticalSection.Create;
end;
procedure TLiberador.TLiberadorThread.BeforeDestruction;
begin
inherited;
Self.FQueue.Free;
Self.FCritical.Free;
end;
procedure TLiberador.TLiberadorThread.Execute;
begin
inherited;
NameThreadForDebugging(AnsiString(Self.ToString));
IdentificarPID(Self.ToString);
while not (Self.Terminated) do
begin
Sleep(10);
if (Self.FQueue.Count > 0) then
begin
Self.FQueue.Pop.Free;
end;
end;
end;
procedure TLiberador.TLiberadorThread.WhenTerminate(Sender: TObject);
begin
Sleep(10);
end;
{ TLiberador }
procedure TLiberador.AddObject(poObject: TObject);
begin
Self.FDetail.AddObject(poObject);
end;
procedure TLiberador.AfterConstruction;
begin
inherited;
Self.FDetail := TLiberadorThread.Create(True);
Self.FDetail.Start;
end;
procedure TLiberador.BeforeDestruction;
begin
inherited;
Self.FDetail.Terminate;
if not (Self.FDetail.Suspended) then
Self.FDetail.WaitFor;
Self.FDetail.Free;
end;
{ TForm2 }
procedure TForm2.Button1Click(Sender: TObject);
begin
Self.FTeste.AddObject(TObject.Create);
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
Self.g4MemoryMonitor1.Active := True;
Self.FTeste := TLiberador.Create;
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
Self.FTeste.Free;
end;
end.
Existem outras novidades que talvez os programadores Delphi da "old school" não conheçam (a começar por mim). Dê uma olhada neste link: http://edn.embarcadero.com/article/34324