GARANTIR DESCONTO

Fórum Como obter a variável de instância de uma classe? #370407

12/05/2009

0

Caros colegas

Considerando que eu tenho estas classes com as variáveis de instância ncliente e nfornecedor

//classe cliente
type
   Tncliente = class(TForm)
   private
      { Private declarations }
   public
      { Public declarations }
   end;

var
   ncliente: Tncliente;

Initialization
  Classes.RegisterClass(Tncliente)
Finalization
  Classes.UnRegisterClass(Tncliente) 




//classe fornecedor
type
   Tnfornecedor = class(TForm)
   private
      { Private declarations }
   public
      { Public declarations }
   end;

var
   nfornecedor: Tnfornecedor;

Initialization
  Classes.RegisterClass(Tnfornecedor)
Finalization
  Classes.UnRegisterClass(Tnfornecedor) 


e dado o código abaixo:

procedure TnPrincipal.CriarForm(TjanelaDestino : string);
var
  AClassJanelaDestino : TFormClass;
  AFormJanelaDestino  : TForm;
begin
   AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino));  //TjanelaDestino recebe Tncliente ou Tnfornecedor
   if AClassJanelaDestino <> nil then
   begin
      Application.CreateForm(AClassJanelaDestino, AFormJanelaDestino);
   end
   else
      raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´);
end;


Em vez de jogar o Pointer em AFormJanelaDestino,
como poderia jogar o pointer diretamente na variável de instância da classe passada como parâmetro?

procedure TnPrincipal.CriarForm(TjanelaDestino : string);
var
  AClassJanelaDestino : TFormClass;
  /////////AFormJanelaDestino  : TForm;
begin
   AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino));  //TjanelaDestino recebe Tncliente ou Tnfornecedor
   if AClassJanelaDestino <> nil then
   begin
      Application.CreateForm(AClassJanelaDestino, aqui variável de isntância da classe Tncliente ou TnFornecedor);
   end
   else
      raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´);
end;


Ou seja, temos como pegar a classe passando uma string. A pergunta que fica é se tem como pegar a variável de instância de forma semelhante como pegamos a classe?

Agradeço a todos que puderem contribuir

Delmar


Delmar

Delmar

Responder

Posts

13/05/2009

.lg.

Ola Delmar,

Se não for o form principal, descarte a ideia de:
var
  ncliente: Tncliente

Você pode criar sua classe sem isso. Infelizmente, eu sei o porque o form principal do delphi o cria, mas não sei explicar o porque.
Se for units diferentes, lembrese de dar um [b:d1754e7728]Uses[/b:d1754e7728] na unit que vc quer usar.

Use o nome de sua classe como o tipo de sua variável.
AFormJanelaDestino: Tnfornecedor;


Instancia:
AFormJanelaDestino := TnFornecedor.Create;

E quando não precisar dela, destrua e limpe da memoria.
FreeAndNil(AFormJanelaDestino);


Se eu estiver errado favor me corrigir.
Eu faço assim.

Espero que lhe ajude.


Responder

Gostei + 0

13/05/2009

Delmar

Bom dia .lg.


Use o nome de sua classe como o tipo de sua variável. Código: AFormJanelaDestino: Tnfornecedor;


Como esse procedimento é uma especie de factory de TForms, baseado no exemplo, ele pode receber um Tncliente ou um Tnfornecedor, então eu não posso ter um tipo fixo. Ao menos que existe como fazer a declaração do tipo se auto-ajustar ao parâmetro passado.

Por outro lado, eu penso que se o Application.CreateForm saber criar um formulário e ao mesmo tempo setar sua variável de instância para apontar para o objeto criado, deve existir um jeito de fazer isso, pois por traz dos bastidores ele faz isso de alguma forma, acredito.


Responder

Gostei + 0

13/05/2009

.lg.

Entendi oque você quis dizer. Infelizmente não tenho conhecimento suficiente para poder lhe dar uma solução.

Minhas desculpas,
Abraços.

Att,
.lg.


Responder

Gostei + 0

13/05/2009

Delmar

De qualquer forma obrigado .lg.

E os colegas que trabalham mais intensamente com POO ou que têm mais contato com as certificações do Delphi ariscariam um palpite de como resolver esta situação?


Responder

Gostei + 0

14/05/2009

Marco Salles

Serai isto que vc quer ???

procedure TForm1.CriarForm(TjanelaDestino : string);
begin
try
with TComponentClass(findclass(TjanelaDestino)).Create(nil) as TForm do
begin
showModal;
free;
end;
except
 Raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´);
end;
end;


bem , mas eu gosto e uso é o factory methods

pode ser visto em :

http://forum.devmedia.com.br/viewtopic.php?t=74823&highlight=factory

em seguida aprece um nova idéia usando Interfaces . Mas esta eu não
coloquei emlinha de produç]ao

http://forum.devmedia.com.br/viewtopic.php?p=328239&highlight=#328239


Responder

Gostei + 0

14/05/2009

Delmar

Boa tarde Marco Salles

o que eu quero é isto:

Application.CreateForm(AClassJanelaDestino, aqui variável de isntância da classe Tncliente ou TnFornecedor); 



Ou seja, quando Application.CreateForm criar uma instância da classe, fazer com que a variável de instância daquela classe aponte para o objeto criado.

Em outras palavras:

Se foi passado TnCliente, quando Application.CreateForm criar o objeto, a variável nCliente deve apontar para o endereço do objeto criado.

Se foi passado TnFornecedor, quando Application.CreateForm criar o objeto, a variável nFornecedor deve apontar para o endereço do objeto criado.

Do meu entendimento, quando fizemos um Application.CreateForm o CreateForm faz o trabalho de criar um objeto e faz com que a variável aponte para este objeto.

O problema é que, no exemplo que estou propondo, temos uma factory e não estou conseguindo pegar a variável da classe passada como parâmetro, pois eu posso encontrar diferentes classes de acordo com uma string passada como parâmetro para o comando TFormClass(GetClass(TjanelaDestino))


Ou seja, dada uma string, eu consigo obter a classe usando GetClass, mas ainda não descobri como pegar a sua variável. Teria que ter um comando GetVariable para fazer o que faz GetClass, só que GetClass pega a Classe e GetVariable deveria pegar a variável.


Pronto, expliquei de várias maneiras a mesma coisa.


Responder

Gostei + 0

14/05/2009

Marco Salles

Se foi passado TnCliente, quando Application.CreateForm criar o objeto, a variável nCliente deve apontar para o endereço do objeto criado.


Por outro lado, eu penso que se o Application.CreateForm saber criar um formulário e ao mesmo tempo setar sua variável de instância para apontar para o objeto criado


Mas se o proprio Application.CreateForm qnd cria o Objeto ele devolve o
ponteiro para o Objeto Recem Criado

Application.CreateForms(ClasseFormulário, Var formulario) ; Ou mesmo Formulario :=TClasseFormulario.Create(proprietario)


não entendo qnd vc disse que o delphi faz isto atras dos bastidores
se tudo indica que ele usa a classe e a variavel digamos assim???

p:s Não estou usando uma linguagem tecnica


Responder

Gostei + 0

14/05/2009

Delmar

Olá amigos

Visitei o método CriarForm do Tapplication e evolui um pouco


Consegui algum progresso assim

procedure TnPrincipal.CriarForm(TjanelaDestino : string; var Reference);
var
  AClassJanelaDestino : TFormClass;
begin
   AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino));  //TjanelaDestino recebe Tncliente ou Tnfornecedor
   if AClassJanelaDestino <> nil then
   begin
      Application.CreateForm(AClassJanelaDestino, TForm(Reference));
      TForm(Reference).Show;
   end
   else
      raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´);
end;



Só que dessa forma minha chamada fica assim

CriarForm(´TnCliente´, nCliente);



E eu queria assim:

CriarForm(´TnCliente´);



Responder

Gostei + 0

14/05/2009

Delmar

não entendo qnd vc disse que o delphi faz isto atras dos bastidores se tudo indica que ele usa a classe e a variavel digamos assim???


Sim, mas a classe eu estou pegando com GetClass, dada uma string contendo o nome da classe, mas eu não posso colocar ali na variável fixo nCliente ou nFornecedor, porque eu não sei qual destes dois termos, vai depender de qual classe eu passei. Só que mesmo tendo pego a classe eu não sei extrair de dentro dela o nome da variável.

Sua linguagem está ótima, quanto mais técnica, melhor. Eu não entendo muito de POO, mas programo estruturado em Delphi desde 98, então pode mandar bala, se eu não entender algo, eu vou pro Help do Delphi.


o meu problema não é usar estes comandos
Application.CreateForms(ClasseFormulário, Var formulario) ; Formulario :=TClasseFormulario.Create(proprietario);

Isso aí eu tiro de letra, o desafio é pegar a variável, qdo fornecido apenas uma string representando o nome da classe.


Responder

Gostei + 0

14/05/2009

Marco Salles

procedure Tform1.CriarForm(TjanelaDestino:string);
o desafio é pegar a variável, qdo fornecido apenas uma string representando o nome da classe.


Sera que vc por acaso não estaria se refrindo ao FindClass() ????

var
  AClassJanelaDestino : TFormClass;
  variavel:Tform;
begin
   AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino));  //TjanelaDestino recebe Tncliente ou Tnfornecedor
   if AClassJanelaDestino <> nil then
   begin
      variavel:=Tform(findclass(TJanelaDestino));
      Application.CreateForm(AClassJanelaDestino,variavel);
      variavel.Show;
   end
   else
      raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´);
end;



Responder

Gostei + 0

14/05/2009

Fabriciocolombo

Acho que está faltando a pergunta mais simples. Para que vc precisa dessa variável global? Mostre como vc está chamando sua factory.

Factories, normalmente são functions e não procedures, então vc poderia fazer assim:

function TFactoryForm.CriarForm(TjanelaDestino : string): TForm; 
var 
  AClassJanelaDestino : TFormClass; 
begin 
   AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino));  //TjanelaDestino recebe Tncliente ou Tnfornecedor 
   if AClassJanelaDestino <> nil then 
   begin 
      Result := AClassJanelaDestino.Create(nil); 
   end 
   else 
      raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); 
end;


e chamar assim:

procedure x;
var
  vClient: TForm;
begin
  vClient := FactoryForm.CriarForm(´Tncliente´);
  try
    vClient.ShowModal;
  finally
    FreeAndNil(vClient);
  end;
end;



Responder

Gostei + 0

14/05/2009

Delmar

Boa noite Marco Salles

Sera que vc por acaso não estaria se refrindo ao FindClass() ????


Não. FindClass está funcionando perfeitamente.


Responder

Gostei + 0

14/05/2009

Delmar

Boa noite FabricioColombo

Acho que está faltando a pergunta mais simples. Para que vc precisa dessa variável global?

Digamos que seja software legado ou também para fins didático.

Mostre como vc está chamando sua factory.

Como ainda não consegui o que eu queria eu mudei para isso:
procedure TnPrincipal.CMavisos(var Msg: TMessage);
var
   AClassJanelaDestino: TFormClass;
   AForm: TForm;
   CriarForm: procedure(aCodigo: string) of object;
begin
   AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); TPersistent
   if AClassJanelaDestino <> nil then
   begin
      AForm := AClassJanelaDestino.Create(self);
      try
         @CriarForm := AForm.MethodAddress(´CriarForm´);
         if @CriarForm <> nil then
            CriarForm(IntToStr(Msg.WParam))
         else
            raise Exception.Create(´O procedimento CriarForm não está disponível na Classe ´ + TjanelaDestino);
         AForm.Free;
      except
         AForm.Free;
         raise;
      end;
   end
   else
      raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´);
end;

Como MethodAddress é um método de classe eu criei dentro de TnCliente e também dentro de TnFornecedor o método CriarForm. Agora sim, em cada classe, dentro do CriarForm, posso executar, respectivamente, o seguinte:

Application.CreateForm(TnCliente, nCliente); 

e
Application.CreateForm(TnFornecedor, nFornecedor); 

e com isso deixar o legado nCliente e nFornecedor abastecido com o endereço do objeto.

Factories, normalmente são functions

Sim, eu conheço essa construção usando função que retorna TForm.

Porém, eu venho de um PostMessage, ou seja, a janela que disparou PostMessage pode até já ter sido destruída. Então eu não posso retornar nada para a janela que dispara PostMessage. E tem mais, a janela que dispara PostMessage não sabe nada sobre TnCliente e nem sobre TnFornecedor, caso contrário, eu poderia passar a classe a a referencia, e aí teria sido uma maravilha, era só fazer a função tal qual vc me sugeriu.


Responder

Gostei + 0

11/06/2018

Smart Sistemas

Olá Delmar.
Estou tentando fazer exatamente a mesma coisa que você. Conseguiu uma solução para isso?
Responder

Gostei + 0

11/06/2018

Emerson Nascimento

como você chega em

CriarForm(´TnCliente´);

ou

CriarForm(´Tnfornecedor´);

?



Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar