Poo - Erro ao destruir dois objetos com a mesma classe com pais diferentes

Delphi

12/08/2012

Olá bom dia!

Tenho um erro ao destruir um Objeto em Poo.

Ao Cria um formulario, crio os objeto Produtos = Prod e Nfentrada = Nfe;

Quando usava somente o objeto Nfe ao destruir o objeto tudo ocorria bem, mas
agora estou instanciando tbém o objeto Produtos e agora ocorre um erro ao destruir o objeto Nfe.
Veja a rotina abaixo.
Nesta situacao o erro ocorre ao destruir o objeto Nfe, se eu inverte ocorre no objeto Prod exatamente
em Proutos ao destruir Tributos e Unid.Medida.


Obs: no momento fiz uma correção e desprezei o Obj Produto instanciado em Nfentrada, mas
para saber pq acontece o erro resolvi continuar.




Veja como está minha classe Produtos:
------------------------------------------
--Tem a classe Produtos, Tributos, Unimed
--


Veja como está minha classe Nfe:
------------------------------------------
--Tem a classe Nfe, ItensNfe e ItensNfe-Produtos
--


Quando fecho o form Nfentrada o Prod.Destrua_se, Prod := nil, até ai td bem,
destru-o Tributos e Unimed ref. a Produtos.

E quando destruo o obj Nfe.Destrua_se ocorre um erro na classe Produtos ao destruir
Tributos e Unid.Medida ref. a Nfe.

Então pergunto pq isto ocorre ?

Cada objeto criado tem sua ID, o q deve ocorre neste caso, alguem saberia me dizer o q está errado com meu código?


Veja minhas classe abaixo, Produtos e Nfentrada.





Desde ja meus agradecientos a quem puder ajudar.



ANT.CARLOS/SP







===================================================================
Fecha Formulario Nota Fiscal Entrada
===================================================================
procedure TFrm_Nfe.FormClose(Sender: TObject; var Action: TCloseAction);
begin
inherited;

Prod.Destrua_se;
Prod := nil;

Cds_Auxiliar.EmptyDataSet;
DMNFE.Sql_PesqCST.Close;
DMTRIB.Sql_PesqTrib2.Close;
Nfe.Destrua_se;
Nfe := nil;
end;



===================================================================
CLASSE - NOTA FISCAL ENTRADA
===================================================================
Type TNfentrada = Class
private

FvTotIcms : Currency;
FvlSeguro : Currency;
FvlIcmsbt : Currency;

FItens : TNfe_Itens; //....Itens da Nota

Protected

Public

constructor Crie_Instancia;
destructor Destrua_se;

Property Itens : TNfe_Itens Read FItens Write FItens;

End;


constructor TNfentrada.Crie_Instancia;
begin
Itens := TNfe_Itens.Crie_Instancia;
Itens.Produto := TProduto.Crie_Instancia;

end;

destructor TNfentrada.Destrua_se;
begin
Itens.Produto.Destrua_se;
Itens.Destrua_se;
Itens := nil;
end;

constructor TNfe_Itens.Crie_Instancia;
begin

end;

destructor TNfe_Itens.Destrua_se;
begin

end;




===================================================================
CLASSE - PRODUTO
===================================================================
Type TProduto = Class
protected

Private
Sqlx : TSqlQuery;

FCodtrib : Integer;
FcodProd : String;
FUnimed : String;
FTrib : TTributos;
FUnid : TUnimed;


procedure Set_Produto(const Value: String);
procedure Set_Tributos(const Value: Integer);
procedure Set_Unimedida(const Value: String);

Public

constructor Crie_Instancia;
destructor Destrua_se;

Property codProd : String Read FcodProd Write Set_Produto;
Property descricao : String Read Fdescricao Write Fdescricao;
Property Unimed : String Read FUnimed Write Set_Unimedida;
Property Codtrib : Integer Read FCodtrib Write Set_Tributos;
Property Trib : TTributos Read FTrib;
Property Unid : TUnimed Read FUnid;

End;


constructor TProduto.Crie_Instancia;
begin
FTrib := TTributos.Crie_Instancia;
FUnid := TUnimed.Crie_Instancia;
end;

destructor TProduto.Destrua_se;
begin
FreeAndNil(Sqlx);
FTrib.Destrua_se;
FUnid.Destrua_se;

FTrib := nil;
FUnid := nil;
end;




Antonio Jesus

Antonio Jesus

Curtidas 0

Respostas

Joel Rodrigues

Joel Rodrigues

12/08/2012

O erro que ocorre é de Access Violation?
Talvez seja o seguinte: a classe NFe possui os produtos, os quais são destruidos no seu destrutor. Quando você destróis os produtos ´´por fora´´, o objeto NFe não consegue dstruí-los novamente.
Eu tenho duas sugestões:
1) É realmente necessário destruir os produtos antes da NFe?
2) No destrutor da NFe, verifique se os itens estão instanciados antes de tentar destruí-los. Para isso, use a função Assigned.
GOSTEI 0
Antonio Jesus

Antonio Jesus

12/08/2012

Olá bom dia!
Obrigado pela atenção!

Então quando eu aprendi Poo, me disseram q eu poderia criar varios Objestos de uma mesma classe, pois cada obj tem sua ID
e isto não implicaria na destruição do mesmo, mesmo tendo a classe mãe como origem.

Em Java faço isto e vejo q o ID faz sua função, pois crio uma lista de Pessoas e tudo funciona bem.

Sei o q vc disse acima é o correto, só quero fazer entender o uso do ID, ou tenho q criar Objetos com nomes diferentes em Delphi?

Sobre o Assigned fiz isto, mas até então achava errado, pois um Objeto destruir um objeto não relacionado a ele.

100+

ANT.CARLOS/SP
GOSTEI 0
Joel Rodrigues

Joel Rodrigues

12/08/2012

Rapaz, pode ser que eu não tenha entendido bem o seu código, mas a minha ideia era a seguinte:

- NFe possui um Lista de Produtos.
- No destrutor da NFe, você destrói a lista de produtos.
- -Se os produtos da lista já tiverem sido destruídos, antes do destrutor da NFe, a NFe não conseguirá acessá-los para destruí-los. Daí o erro de Access Violation.
GOSTEI 0
Antonio Jesus

Antonio Jesus

12/08/2012

ok, então vou explicar melhor

Veja a situacao

1-Instanciei um Obj Produtos (Prod - Id 1444),
2-Instancieu Nota Fiscal entrada (Nfe - Id 1888) q por sua vez tem itens e o Otens tem um tributo Produtos (IProd).


Então instanciei 2 objetos distintos Prod e Nfe q tem em seus itens uma lista de produtos.

A questão é pq q quando destru-o o Objeto Prod ele destroi o Itens.IProd e vice versa?

Não era para acontece isto, se eu destru-o o Obj Prod o Nfe + itens.Iprod deveria ficar intacto?

Ou eu estou com minha lógica errado quanto a Poo no Delphi ?


Entendeu onde quero chegar ?


100+

ANT.CARLOS/SP




GOSTEI 0
Joel Rodrigues

Joel Rodrigues

12/08/2012

ACHO que entendi. Se for o que eu estou pensando, isso se dá devido às classes serem tipos ´´por referência´´. Ou seja, quando você atribui o valor de uma classe a outro objeto, não é feita uma nova cópia, mas sim os dois objetos passam a apontar para a mesma posição na memória. Quando você altera um, ambos sofrem a alteração.
GOSTEI 0
Antonio Jesus

Antonio Jesus

12/08/2012

Hummm!!!! Entendei, então como resolver este problema ?

Pois desejaria no obj Prod ter um produto cod: 00280 e em Nfe Itens.Produtos = 00380.

Não seria possível fazer isto então, uma vez q tenho 2 objetos distintos ?

Pois estou indignado com isto, pois em Java vejo da forma como penso, pq aqui seria diferente uma vez q Poo é padronizado?


100+

ANT.CARLOS/SP
GOSTEI 0
Antonio Jesus

Antonio Jesus

12/08/2012

Olá boa noite!

contionuando fiz um teste para ver se o Obj Produto guardava em memoria um produto e no Nfe outro produto.
Sim isto acontece.
Rastreando a destruilçao do Nfe vi q o mesmo destrou a Unidade de medida, Tributos e Produtos, até ai td bem.
Quando destruo o Produto, o mesmo esta Assigned, mas mesmo assim ocorre o erro de violação.

100+

ANT.CARLOS/SP
GOSTEI 0
POSTAR