Como obter a variável de instância de uma classe?
Caros colegas
Considerando que eu tenho estas classes com as variáveis de instância ncliente e nfornecedor
e dado o código abaixo:
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?
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
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
Curtidas 0
Respostas
.lg.
12/05/2009
Ola Delmar,
Se não for o form principal, descarte a ideia de:
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.
Instancia:
E quando não precisar dela, destrua e limpe da memoria.
Se eu estiver errado favor me corrigir.
Eu faço assim.
Espero que lhe ajude.
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.
GOSTEI 0
Delmar
12/05/2009
Bom dia .lg.
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.
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.
GOSTEI 0
.lg.
12/05/2009
Entendi oque você quis dizer. Infelizmente não tenho conhecimento suficiente para poder lhe dar uma solução.
Minhas desculpas,
Abraços.
Att,
.lg.
Minhas desculpas,
Abraços.
Att,
.lg.
GOSTEI 0
Delmar
12/05/2009
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?
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?
GOSTEI 0
Marco Salles
12/05/2009
Serai isto que vc quer ???
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
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
GOSTEI 0
Delmar
12/05/2009
Boa tarde Marco Salles
o que eu quero é isto:
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.
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.
GOSTEI 0
Marco Salles
12/05/2009
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
GOSTEI 0
Delmar
12/05/2009
Olá amigos
Visitei o método CriarForm do Tapplication e evolui um pouco
Consegui algum progresso assim
Só que dessa forma minha chamada fica assim
E eu queria assim:
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´);
GOSTEI 0
Delmar
12/05/2009
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.
GOSTEI 0
Marco Salles
12/05/2009
procedure Tform1.CriarForm(TjanelaDestino:string);
Sera que vc por acaso não estaria se refrindo ao FindClass() ????
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;
GOSTEI 0
Fabriciocolombo
12/05/2009
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:
e chamar assim:
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;
GOSTEI 0
Delmar
12/05/2009
Boa noite Marco Salles
Não. FindClass está funcionando perfeitamente.
Sera que vc por acaso não estaria se refrindo ao FindClass() ????
Não. FindClass está funcionando perfeitamente.
GOSTEI 0
Delmar
12/05/2009
Boa noite FabricioColombo
Digamos que seja software legado ou também para fins didático.
Como ainda não consegui o que eu queria eu mudei para isso:
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:
e
e com isso deixar o legado nCliente e nFornecedor abastecido com o endereço do objeto.
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.
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.
GOSTEI 0
Smart Sistemas
12/05/2009
Olá Delmar.
Estou tentando fazer exatamente a mesma coisa que você. Conseguiu uma solução para isso?
Estou tentando fazer exatamente a mesma coisa que você. Conseguiu uma solução para isso?
GOSTEI 0
Emerson Nascimento
12/05/2009
como você chega em
CriarForm(´TnCliente´);
ou
CriarForm(´Tnfornecedor´);
?
CriarForm(´TnCliente´);
ou
CriarForm(´Tnfornecedor´);
?
GOSTEI 0
Smart Sistemas
12/05/2009
como você chega em
CriarForm(´TnCliente´);
ou
CriarForm(´Tnfornecedor´);
?
CriarForm(´TnCliente´);
ou
CriarForm(´Tnfornecedor´);
?
são menus dinâmicos, carregados conforme as opções do usuário. Cada menu tem o string contendo o nome da sua classe.
GOSTEI 0