Array
(
)

devo usar FreeAndNil ou Destructor Destroi?

Cherodogo
   - 10 abr 2006

Estou iniciando em Orientação a Objetos e me deparei com uma dúvida. Suponham a minha classe abaixo:

Type
TFaltas = Class(TObject)
MeuMemo : TMemo;
NumeroDeFaltas : Integer;
Constructor Cria;
Destructor Destroi;
End;

Var
UmaFalta : TFalta;
.
.
.
Implementation
Constructor TFaltas.Cria;
Begin
MeuMemo := TMemo.Create;
NumeroDeFaltas := 0;
End;

Destructor TFaltas.Destroi;
Begin
FreeAndNil(MeuMemo);
End;
.
.
.
{Chamando o construtor e o destruidor}

Procedure UsaOObjeto;
Begin
UmaFalta := TFalta.Create;
{agora vem a dúvida: o que uso para liberar o objeto?}
UmaFalta.Destroi;
UmaFalta.Free ou
FreeAndNil(UmaFalta);
End;

Então fico na dúvida de que método usar para liberar o objeto. Sei que se minha classe não contivesse nenhum outro objeto na sua definição, o ideal seria usar FreeAndNil, mas UmaFalta cria um outro objeto dentro dele (um memo) no momento em que é instanciado. Nessas condições, como devo liberar da memória o objeto UmaFalta?
Agradeço o interesse.


Massuda
   - 10 abr 2006

Algumas padronizações do Delphi...[list:4d720670d7][*:4d720670d7]O construtor sempre chama-se Create.[*:4d720670d7]O destrutor sempre chama-se Destroy[*:4d720670d7]Para destruir um objeto, use Free; evite chamar Destroy diretamente.[/list:u:4d720670d7]
Embora Delphi permita você ter construtor/destrutor com qualquer nome, geralmente código para Delphi assume que o construtor/destrutor usam os nomes padrão.

Use sempre Free (ou FreeAndNil) ao invés de Destroy. Free verifica se o objeto a ser liberado é ou não nil (embora não verifique se o objeto já foi destruído), coisa que Destroy não faz.

Free e FreeAndNil fazem basicamente a mesma coisa, o diferencial é que FreeAndNil irá atribuir nil à referencia ao objeto que você está liberando. Isso é útil no caso de objetos de escopo global, mas não faz diferença no caso de objetos de escopo local.


Lorde_morte.
   - 10 abr 2006


Citação:
o diferencial é que FreeAndNil irá atribuir nil à referencia ao objeto que você está liberando. Isso é útil no caso de objetos de escopo global, mas não faz diferença no caso de objetos de escopo local.


Apesar de FreeAndNil ser um pouco maior do que Free eu sempre uso o FreeAndNil.


Cherodogo
   - 10 abr 2006


Citação:
Algumas padronizações do Delphi...[list:993002c252][*:993002c252]O construtor sempre chama-se Create.[*:993002c252]O destrutor sempre chama-se Destroy[*:993002c252]Para destruir um objeto, use Free; evite chamar Destroy diretamente.[/list:u:993002c252]
Embora Delphi permita você ter construtor/destrutor com qualquer nome, geralmente código para Delphi assume que o construtor/destrutor usam os nomes padrão.

Use sempre Free (ou FreeAndNil) ao invés de Destroy. Free verifica se o objeto a ser liberado é ou não nil (embora não verifique se o objeto já foi destruído), coisa que Destroy não faz.

Free e FreeAndNil fazem basicamente a mesma coisa, o diferencial é que FreeAndNil irá atribuir nil à referencia ao objeto que você está liberando. Isso é útil no caso de objetos de escopo global, mas não faz diferença no caso de objetos de escopo local.


Ok, Massuda. Mas a minha dúvida ainda é se, usando FreeAndNil(UmaFalta), o memo que faz parte deste meu objeto também será liberado automaticamente.
Abraço.


Cherodogo
   - 10 abr 2006


Citação:
Algumas padronizações do Delphi...[list:634c2706d7][*:634c2706d7]O construtor sempre chama-se Create.[*:634c2706d7]O destrutor sempre chama-se Destroy[*:634c2706d7]Para destruir um objeto, use Free; evite chamar Destroy diretamente.[/list:u:634c2706d7]
Embora Delphi permita você ter construtor/destrutor com qualquer nome, geralmente código para Delphi assume que o construtor/destrutor usam os nomes padrão.

Use sempre Free (ou FreeAndNil) ao invés de Destroy. Free verifica se o objeto a ser liberado é ou não nil (embora não verifique se o objeto já foi destruído), coisa que Destroy não faz.

Free e FreeAndNil fazem basicamente a mesma coisa, o diferencial é que FreeAndNil irá atribuir nil à referencia ao objeto que você está liberando. Isso é útil no caso de objetos de escopo global, mas não faz diferença no caso de objetos de escopo local.


Ok, Massuda. Mas a minha dúvida ainda é se, usando FreeAndNil(UmaFalta), o memo que faz parte deste meu objeto também será liberado automaticamente.
Abraço.


Massuda
   - 10 abr 2006


Citação:
...usando FreeAndNil(UmaFalta), o memo que faz parte deste meu objeto também será liberado automaticamente.
Não. Se você criou um objeto dentro do seu (vou chamar de ´objeto interno´), geralmente é usa responsabilidade liberar esse objeto interno no destrutor do seu objeto.

No seu código original você até fez isso (me desculpe se foi erro de digitação), mas como voicê chamou o destrutor de Destroi, esse destrutor não é executado pelo Free ou FreeAndNil, já que essas funções assumem que o destrutor do objeto chama-se Destroy.

A VCL do Delphi tem um mecanismo diferente de decidir quem deve liberar um objeto baseado no Owner (se você olhar nas classes da VCL verá que várias delas preveem no construtor quem é o Owner - dono - do objeto). Nesse caso, é responsabilidade do Owner destruir o objeto.


Cherodogo
   - 10 abr 2006


Citação:

Citação:
...usando FreeAndNil(UmaFalta), o memo que faz parte deste meu objeto também será liberado automaticamente.
Não. Se você criou um objeto dentro do seu (vou chamar de ´objeto interno´), geralmente é usa responsabilidade liberar esse objeto interno no destrutor do seu objeto.

No seu código original você até fez isso (me desculpe se foi erro de digitação), mas como voicê chamou o destrutor de Destroi, esse destrutor não é executado pelo Free ou FreeAndNil, já que essas funções assumem que o destrutor do objeto chama-se Destroy.

A VCL do Delphi tem um mecanismo diferente de decidir quem deve liberar um objeto baseado no Owner (se você olhar nas classes da VCL verá que várias delas preveem no construtor quem é o Owner - dono - do objeto). Nesse caso, é responsabilidade do Owner destruir o objeto.


Quer dizer então, que, se eu trocar o nome do meu destruidor e chamá-lo de Destructor Destroy, o FreeAndNil(UmaFalta) vai liber o objeto UmaFalta e o objeto Memo que está dentro dele também?

Type
TFaltas = Class(TObject)
MeuMemo : TMemo;
NumeroDeFaltas : Integer;
Constructor Create;
Destructor Destroy;
End;

Var
UmaFalta : TFalta;
.
.
.
Implementation
Constructor TFaltas.Create;
Begin
MeuMemo := TMemo.Create;
NumeroDeFaltas := 0;
End;

Destructor TFaltas.Destroy;
Begin
FreeAndNil(MeuMemo);
End;
.
.
.
{Chamando o construtor e o destruidor}

Procedure UsaOObjeto;
Begin
UmaFalta := TFalta.Create;
{agora vem a dúvida: o que uso para liberar o objeto?}
UmaFalta.Destroy; //com y no final (risos)
UmaFalta.Free ou
FreeAndNil(UmaFalta);
End;

Valeu, Massuda!


Massuda
   - 10 abr 2006


Citação:
...se eu trocar o nome do meu destruidor e chamá-lo de Destructor Destroy, o FreeAndNil(UmaFalta) vai liber o objeto UmaFalta e o objeto Memo que está dentro dele também?
Sim porque o destrutor que você escreveu faz isso. E isso vai ocorrer tanto no caso de você usar Free ou FreeAndNil.

Um detalhe importante é que o destrutor Destroy é virtual, o que significa que você deve declarar seu destrutor Destroy com override e incluir um inherited como sendo a última linha do seu destrutor...#Código

Type 
TFaltas = Class(TObject)
...
Destructor Destroy; override;
...
end;

Destructor TFaltas.Destroy;
Begin
FreeAndNil(MeuMemo);
inherited;
End;

{Chamando o construtor e o destruidor}

Procedure UsaOObjeto;
Begin
UmaFalta := TFalta.Create;
...
UmaFalta.Free
ou
FreeAndNil(UmaFalta);
End;



Adriano Santos
   - 10 abr 2006

Só uma correção no constructor. A assinatura ´correta´ é:

#Código


Type
TFaltas = Class(TObject)
MeuMemo : TMemo;
NumeroDeFaltas : Integer;
constructor Create(AOWner: TObject);override;
destructor destroy;override;
End;



Massuda, me corrija se eu estiver incorreto. O override diz ao compilador que o create e o destructor pode ser sobrepostos correto?


Cherodogo
   - 10 abr 2006

Cara, valeu mesmo. Muito obrigado, Massuda. Baita mão na roda. Já aprendi um pouco mais de POO contigo.
Abraço.


Massuda
   - 10 abr 2006


Citação:
O override diz ao compilador que o create e o destructor pode ser sobrepostos correto?
Acho que o mais correto é interpretar o override como sendo ´o construtor/destrutor/método foi sobreposto´. Note que virtual pode ser interpretado como sendo ´o construtor/destrutor/método pode ser sobreposto´


Citação:
constructor Create(AOWner: TObject);override;
No caso, como TFaltas é derivado de TObject, o código original é correto. Sua sugestão seria válida se TFaltas fosse derivado, no caso de classes da VCL, de TComponent.


Adriano Santos
   - 10 abr 2006


Citação:

Citação:
O override diz ao compilador que o create e o destructor pode ser sobrepostos correto?
Acho que o mais correto é interpretar o override como sendo ´o construtor/destrutor/método foi sobreposto´. Note que virtual pode ser interpretado como sendo ´o construtor/destrutor/método pode ser sobreposto´


Citação:
constructor Create(AOWner: TObject);override;


No caso, como TFaltas é derivado de TObject, o código original é correto. Sua sugestão seria válida se TFaltas fosse derivado, no caso de classes da VCL, de TComponent.


Ah, entendi tudo agora...vlw


Fabiano Góes
   - 12 abr 2006

Caraca, esse é mesmo o melhor forum Delphi do planeta.

Caras como Massuda, Adriano Santos, Martins, Rjun e muitos outros
sempre dando a maior força.

Ai brother vcs são firmeza mesmo !!!!

Espero um dia ter pelo menos um pouco do conhecimento que vcs tem,
pra poder ajudar aqui no forum tambem !!!!

Um grande abraço !!!!!


Martins
   - 12 abr 2006


Citação:
Caraca, esse é mesmo o melhor forum Delphi do planeta.

Caras como Massuda, Adriano Santos, Martins, Rjun e muitos outros
sempre dando a maior força.

Ai brother vcs são firmeza mesmo !!!!

Espero um dia ter pelo menos um pouco do conhecimento que vcs tem,
pra poder ajudar aqui no forum tambem !!!!

Um grande abraço !!!!!


Realmente tem muitos colegas bons em desenvolvimento.

Citação:

Caras como Massuda, Adriano Santos, Martins, Rjun e muitos outros
sempre dando a maior força.


eu sou um mero aprendiz ainda, mas todos concordam q o Massuda é um dos muitos gurus deste fórum, q conta com a participação de bons profissionais.


Citação:

Espero um dia ter pelo menos um pouco do conhecimento que vcs tem,
pra poder ajudar aqui no forum tambem !!!!


Com certeza vc chegará ao seu objetivo, com dedicação vc conseguirá.

Boa sorte!


Adriano Santos
   - 13 abr 2006


Citação:
...Adriano Santos...


Heheh, obrigado por citar meu nome Fabiano, é bom ter o reconhecimento da galera. Tb sou um mero espectador, e como aprendi muito aqui, e continuo aprendendo, faço questão de ajudar a todos. Fiz muitos amigos no fórum, e com vc não será diferente. Pode contar comigo.


Um forte abraço


Fabiano Góes
   - 13 abr 2006

Olha só pessoal, eu citei apenas alguns nomes que me vieram na cabeça na hora, alguns caras que já me ajudaram ( Aroldo Zanela, Marcos Salles, Gandalf, Afarias )porem não queria ser injusto com ninguem, pois se for descrever todos os nomes dos caras que se dedicam a ajudar a galera a lista seria enorme, mais como já citei alguns tem um cara que poderia ficar de fora que é o ´Michael´ que alem de ajudar com o problema entra em uns detales didaticos muito importantes.

Em fim, o que eu queria dizer é que esse realmente é o melhor forum do Brasil se não do planeta.

Valeu ai pessoal !!!!
Boa Pascoa pra todos !!!!!!


Adriano Santos
   - 16 abr 2006


Citação:

Em fim, o que eu queria dizer é que esse realmente é o melhor forum do Brasil se não do planeta.


Pode crer Fabiano, olha desde quando eu sou cadastrado, puts meu...sou viciado nisso...hehehe...