Cadastre-se Revistas DevMedia Cursos
 

  DevMedia Spaces
  Resumo de Vitor Luiz Rubio
Busca autor:


Últimos 50 comentários: (clique aqui para ver todos os comentários)
1 - 30/4/2013 18:44 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
VITOR RUBIO Na verdade eu cometi um erro aqui, além de ter me expressado mal. Não é quando você converte (objeto as Interface).Metodo que ocorrem erros, e sim quando você converte um objeto para uma interface passando a variável interface para um método.
Quando se chega ao final do método o contador de referencias da interface chega a zero, porque ele não conta com a referência armazenada na variável objeto FORA do escopo da função. Sendo assim o free é chamado e o objeto destruido prematuramente.
Isso acontece quando você faz algo como:

var
objAviao: TAviao;
objCarro: TCarro;
objBarco: TBarco;
UmObjetoQualquer: TInterfacedObject;

OutroVeiculo: IVeiculo;
OutroCarro: ICarro;
OutroBarco: IBarco;
UmSerVivo: ISerVivo;

begin

//cria os objetos e os mantem com referencia em uma variavel do tipo objeto
objaviao:= TAviao.Create;
objCarro:= TCarro.Create;
objBarco:= Tbarco.Create;
UmObjetoQualquer := TCarro.Create;

//não se deve fazer isso direto com os objetos a não ser que exista uma interface apontando para eles
//fazendo isso o contador de referencia pode zerar
FazVeiculoAndar(objaviao); //saindo do escopo dessa função o argumento atinge refcount zero, destruindo objaviao sem ligar para sua referencia objaviao fora da função
FazVeiculoAndar(objCarro); //saindo do escopo dessa função o argumento atinge refcount zero, destruindo objCarro sem ligar para sua referencia objCarro fora da função
FazVeiculoAndar(objBarco); //saindo do escopo dessa função o argumento atinge refcount zero, destruindo objBarco sem ligar para sua referencia objBarco fora da função

//a partir daqui os objetos não funcionam mais porque o contador de referência foi zerado enquanto o objeto foi
//convertido para interface
objAviao.Voar;
objCarro.Rodar;
objBarco.Velejar;

//a partir daqui o erro pode ocorrer a qualquer momento
(objAviao as IAviao).Voar;
(objCarro as ICarro).Rodar;
(objBarco as IBarco).Velejar;
(UmObjetoQualquer as ICarro).Rodar;


Mas o certo seria criar algo como:


var
aviao: IAviao;
carro: ICarro;
barco: IBarco;

OutroVeiculo: IVeiculo;

begin

//conversão objeto/interface
aviao := TAviao.Create;;
carro := TCarro.Create;
barco := Tbarco.Create;

//isso seria o correto
FazVeiculoAndar(aviao);
FazVeiculoAndar(carro);
FazVeiculoAndar(barco);

aviao.Voar;
carro.Rodar;
barco.Velejar;

No meu código original eu tentei mostrar em um mesmo botão a maneira certa e errada de se fazer isso, deixando parte do código comentado, e isso não ficou muito didático. Eu mesmo me enrolei depois de ler.
Separei esse código em 2 botões, sendo o antigo button3 o modo incorreto, e o novo button8 o método correto. O novo exemplo pode ser baixado em: http://www.vitorrubio.com.br/downloads/CD134_Interfaces_V2_Reformulado.zip
Responder
2 - 30/4/2013 16:43 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
VITOR RUBIO Boa tarde "Softplan". Preciso ver um trecho do seu código e saber qual versão do Delphi você está usando, mas basicamente nesses casos o comportamento esperado seria um erro.
Pode acontecer de o objeto continuar acessível na memória, ou pelo menos alguns métodos que não usem dados internos do objeto, mas esse comportamento não é o esperado e é causado simplesmente por "sujeira" na memória.
Fiz um teste aqui e também funcionou, mesmo assim eu não recomendo. Diferenças na versão do Delphi ou na plataforma podem ocasionar erros.
Na época em que escrevi esse artigo eu usava Delphi XE em um computador de 64 bits, mas não me lembro a versão do Windows.
Hoje fiz o teste tanto no Delphi XE como no Delphi XE 4 usando Windows 7, mas num computador de 32 bits.

O porquê de eu esperar que essa construção cause um erro eu explico:
Dado que interfaces contam referências, então são "Reference Counted" e dado que você cria, converte e usa um objeto dentro de um mesmo método (como o evento click de um botão).

Se você criar o seu objeto já atribuindo ele à uma variável do tipo interface, assim:

var i: ICarro;
begin
i:= TCarro.Create; //1 referencia a um TCarro
(i as ICarro).DeslocarSe; //2 referencias ao TCarro //não precisa disso, apenas mostro como funciona normalmente
i.OutroMetodo;
end; //final do método, 0 referencias ao mesmo TCarro, então o objeto "hospedado" em I é destruido com free.
É esperado que um objeto apresente erro nesse tipo de conversão principalmente quando ele possui outro objeto dentro. Considere um objeto que tenha um StringList como um de seus campos.



var i: TCarro;
begin
i:= TCarro.Create; //1 referencia a um TCarro, no entanto I é um objeto, portanto não conta referências
(i as ICarro).DeslocarSe; //1 referencias ao TCarro hospedado em I convertido para ICarro
i.OutroMetodo; //antes de chegar aqui já temos 0 referências (pois não existe mais a referência temporária que estava sendo usada na conversão para ICarro), portanto Free é acionado e o objeto em I é destruído "por engano". Aqui deve ocorrer um erro ao se executar OutroMetodo, pois o próprio objeto está destruído .
end;

Veja esse exemplo que eu criei no Delphi Xe 4: (em www.vitorrubio.com.br/downloads/TesteInterfaces.zip)

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type

TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;



IVeiculo = interface (iinterface)
['{1D2F0F1D-60CC-47BE-AD22-4DA59D87C7CA}']
procedure DeslocarSe;
procedure Parar;
end;

IVeiculoTerrestre = interface (IVeiculo)
['{CD718BB9-FE3A-4C19-8CE2-01EBB1843B96}']
procedure DeslocarSe;
procedure Parar;
procedure Rodar;
end;

ICarro = interface (IVeiculoTerrestre)
['{3B167780-8EA0-4F59-9DBF-A9F68F54F595}']
procedure DeslocarSe;
procedure Parar;
procedure Rodar;
end;

//TCarro = class(TInterfacedObject, ICarro) //nessa forma você pode atribuir a criação de um TCarro a uma variável ICarro, IVeiculoTerrestre e IVeiculo, mas não pode fazer conversões do tipo AS entre eles
TCarro = class(TInterfacedObject, ICarro, IVeiculoTerrestre, IVeiculo) //esta forma permite qualquer tipo de atribuição e conversão.
private
FPlaca: TStringList;
function GetPlaca: string;
procedure SetPlaca(value: string);
public
constructor Create;
destructor Destroy; override;

procedure DeslocarSe;
procedure Parar;
procedure Rodar;
property Placa: string read GetPlaca write SetPlaca;
end;


var
Form1: TForm1;


implementation

{$R *.dfm}

{ TCarro }

constructor TCarro.Create;
begin
FPlaca := TStringList.Create;
end;

procedure TCarro.DeslocarSe;
begin
ShowMessage(Placa + ' Deslocando-se. ' + self.RefCount.ToString() + ' referências');
end;

destructor TCarro.Destroy;
begin
FPlaca.Free;
inherited;
end;

function TCarro.GetPlaca: string;
begin
Result := FPlaca.Text;
end;

procedure TCarro.Parar;
begin
ShowMessage(Placa + ' Parando.' + self.RefCount.ToString() + ' referências');
end;

procedure TCarro.Rodar;
begin
DeslocarSe;
end;

procedure TCarro.SetPlaca(value: string);
begin
FPlaca.Text := value;
end;

procedure TForm1.Button1Click(Sender: TObject);
var C: TCarro;
begin

C := TCarro.Create; //tenho um objeto, mas C não conta referencias
C.Placa := 'ABC1234';
(C as ICarro).Rodar; //converte e roda na mesma linha, mas zera o contador de referencias na proxima linha
C.Parar; //isso dá erro
C.Rodar;
C.Parar;

end;

procedure TForm1.Button2Click(Sender: TObject);
var C: TCarro;
I: IVeiculoTerrestre;
begin

C := TCarro.Create; //tenho um objeto, mas C não conta referencias
C.Placa := 'ABC1234';
I := (C as ICarro); //Conversão joga para I o controle da contagem de referencias
I.Rodar; //uso normal
I.Parar; //uso normal
I.Rodar; //uso normal
I.Parar; //uso normal

C.Rodar; //Funciona normal, mas não se deve misturar objetos comuns com interfaces, por isso para de usar C uma vez convertido para I
C.Parar; //Funciona normal, mas não se deve misturar objetos comuns com interfaces, por isso para de usar C uma vez convertido para I

end;

procedure TForm1.Button3Click(Sender: TObject);
var C: TCarro;
I: IVeiculo;
begin

C := TCarro.Create; //tenho um objeto, mas C não conta referencias
C.Placa := 'ABC1234';
I := (C as ICarro); //Conversão joga para I o controle da contagem de referencias

I.DeslocarSe;
I.Parar;

//I agora pode ser convertido para qualquer uma das interfaces ancestrais de ICarro sem perder o controle de referência
(I as ICarro).Rodar;
(I as ICarro).Parar;
(I as IVeiculoTerrestre).Rodar;
(I as IVeiculoTerrestre).Parar;
(I as IVeiculo).DeslocarSe;
(I as IVeiculo).Parar;

C.Rodar; //Funciona normal, mas não se deve misturar objetos comuns com interfaces, por isso para de usar C uma vez convertido para I
C.Parar; //Funciona normal, mas não se deve misturar objetos comuns com interfaces, por isso para de usar C uma vez convertido para I

end;

procedure TForm1.Button4Click(Sender: TObject);
var C: TCarro;
iv1, iv2: IVeiculo;
ivt1, ivt2: IVeiculoTerrestre;
ic: ICarro;
begin

C := TCarro.Create;
C.Placa := 'ABC1234';
ic := (C as ICarro);

ivt1 := (C as IVeiculoTerrestre);
iv1 := (C as IVeiculo);

ivt2 := (ic as IVeiculoTerrestre);
iv2 := (ic as IVeiculo);

ic.DeslocarSe;
ic.Parar;
ivt1.Rodar;
ivt1.Parar;
iv1.DeslocarSe;
iv1.Parar;

ivt2.Rodar;
ivt2.Parar;
iv2.DeslocarSe;
iv2.Parar;

end;

procedure TForm1.Button5Click(Sender: TObject);
var C: TCarro;
iv1, iv2: IVeiculo;
ivt1, ivt2: IVeiculoTerrestre;
ic: ICarro;
begin

C := TCarro.Create;
C.Placa := 'ABC1234';
ic := (C as ICarro);

ic.DeslocarSe;
ic.Parar;

if Supports(c, IVeiculoTerrestre, ivt1) then
begin
ivt1.Rodar;
ivt1.Parar;
end;

if Supports(c, IVeiculo, iv1) then
begin
iv1.DeslocarSe;
iv1.Parar;
end;

if Supports(ic, IVeiculoTerrestre, ivt2) then
begin
ivt2.Rodar;
ivt2.Parar;
end;

if Supports(ic, IVeiculo, iv2) then
begin
iv2.DeslocarSe;
iv2.Parar;
end;

end;

procedure TForm1.Button6Click(Sender: TObject);
var C: TCarro;
iv1, iv2: IVeiculo;
ivt1, ivt2: IVeiculoTerrestre;
ic: ICarro;
begin

C := TCarro.Create;
C.Placa := 'ABC1234';
ic := ICarro(C);

ivt1 := IVeiculoTerrestre(C);
iv1 := IVeiculo(C);

ivt2 := IVeiculoTerrestre(ic);
iv2 := IVeiculo(ic);

ic.DeslocarSe;
ic.Parar;
ivt1.Rodar;
ivt1.Parar;
iv1.DeslocarSe;
iv1.Parar;

ivt2.Rodar;
ivt2.Parar;
iv2.DeslocarSe;
iv2.Parar;
end;

end.


Ele
Ele não deu erro como eu esperava no primeiro botão, mesmo assim eu não aconselho a fazer um uso de interfaces + objetos como aquele, principalmente quando seus objetos são passados para métodos ou retornados deles.
Infelizmente não consegui reproduzir esse erro hoje. Compilei e rodei esse código no Delphi XE, no Delphi XE4 e no Lazarus, e em todos os casos funcionou.
Mesmo assim, cuidado redobrado ao se passar variáveis do tipo interface como parâmetros.
Responder
3 - 30/4/2013 08:49 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
SOFTPLAN PLANEJAMENTO E SISTEMAS LTDA Fiquei com uma dúvida na seguinte afirmação:

"Na Listagem 5 a linha (UmObjetoQualquer as ICarro).DeslocarSe cria uma referência a uma interface Icarro durante a conversão que não existirá mais depois da conversão, depois da execução do método, o que fará com que o objeto UmObjetoQualquer seja destruído."

Fiz o teste aqui e o objeto ainda continua existindo. Não seria o correto?
Responder
4 - 21/1/2013 19:15 - ClubeDelphi - Criando uma deskbar - Revista Clube Delphi 134
VITOR RUBIO Infelizmente o stayontop não funcionárá, pois a janela da deskbar ficará na frente da janela maximizada, ocultando uma parte. Responder
5 - 21/1/2013 19:14 - ClubeDelphi - Criando uma deskbar - Revista Clube Delphi 134
VITOR RUBIO Infelizmente eu não sei como o google desktop faz isso. Teria que pesquisar.
Faço uma vaga ideia. Se você tiver o handle de uma janela, obtido com a função GetWindow ou FindWindow, você pode redefinir o tamanho da janela e o estado dela, mesmo se não for uma janela do seu programa.
É bastante trabalhoso encontrar o tamanho máximo, subtrair o tamanho da sua barra e redimensionar todas as outras janelas maximizadas.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633499(v=vs.85).aspx
Responder
6 - 21/1/2013 08:14 - ClubeDelphi - Criando uma deskbar - Revista Clube Delphi 134
PAULO QUICOLI Você tentou setar a propriedade FormStyle para fsStayOnTop ?

Abraço
Responder
7 - 19/1/2013 14:47 - ClubeDelphi - Criando uma deskbar - Revista Clube Delphi 134
Vinícius Valle Muito bom o artigo, mas como eu faria para deixar esta barra sempre visível, forçando o recurso maximizar de outros aplicativos a não cobrir esta (como o google desktop faz, por exemplo)? Responder
8 - 14/5/2012 07:44 - ClubeDelphi - Integre projetos .NET e Win32 - Artigo ClubeDelphi 128
VITOR RUBIO Carlos, desculpe a demora em responder.
Sempre que você adiciona a referencia a uma DLL do tipo COM/ActiveX é criada automaticamente uma DLL com o mesmo nome e um ".interop". Essa faz o "meio de campo" entre as tecnologias COM e .Net.

Geralmente adicionar a referencia é tudo que se precisa, mas você chama seus objetos e funções através do nome da dll original mesmo, não da interop.

A sua DLL tem os métodos públicos e a guid? Pode postar aqui seu projeto para analisarmos?
Responder
9 - 12/5/2012 12:56 - ClubeDelphi - Integre projetos .NET e Win32 - Artigo ClubeDelphi 128
WESLEY YAMAZACK Olá Carlos, sua dúvida foi encaminhada para o autor, peço que aguarde um pouco para que ele possa te atender.

Um abraço.
Responder
10 - 14/4/2012 14:29 - ClubeDelphi - Integre projetos .NET e Win32 - Artigo ClubeDelphi 128
Carlos Cesar D. Campos Quando coloco 'add reference' no Delphi Prism apontando uma DLL criada no Delphi XE (dll criada via objeto com) está vindo c/ o nome de Interop.Com.dll e não consigo acesso a classe para retornar o resultado. Alguém já teve esse problema? Responder
11 - 28/2/2012 17:58 - Easy .net magazine - Visual Studio: Introdução - Easy .net magazine 2
WESLEY YAMAZACK Olá Marcio , tudo bem ?

Sobre a sua solicitação enviamos agora mesmo um e-mail para editor chefe da revista. Assim que obtivermos uma resposta entramos em contato com você novamente, tudo bem pra você?

Obrigado pela ideia.

Um abraço
Responder
12 - 26/2/2012 00:23 - Easy .net magazine - Visual Studio: Introdução - Easy .net magazine 2
Marcio Pereira de Lima Gostei da vídeo aula de tratamento de erros. Mas gostaria de ver uma aula com os tratamentos de erros que estão disponíveis na IDE do Visual Studio.
Obrigado.
Responder
13 - 18/11/2011 09:56 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
Fernanda Lopes Obrigada, vou fazer os testes e qualquer coisa reportarei aqui. Responder
14 - 17/11/2011 10:46 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
VITOR RUBIO Então Fernanda, esse código não funciona com Delphi 7, pois o Delphi 7 não aceita operadores IS e AS para conversões Interface --> Objeto, apenas para Objeto --> Interface.

O que você pode fazer é um typecast forçado, tipo:

var
o: TObject;
o := TObject(minhainterface);

//operações com O agora podem usar is e as

mas cuidado: a linha o := TObject(minhainterface) cria uma nova referencia a uma instância já existente que não será contada pelo contador de referencias da interface. Se algum método ou trecho de código atribuir nil à minhainterface zerando o contador de referências a instância será destruida antes da hora e "o" terá uma referência inválida. Faça testes para verificar leaks ou corrupção de memória com o Fast Memory Manager 4 e não use o método Free em "o".
Responder
15 - 17/11/2011 09:06 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
Fernanda Lopes Estou usando o Delphi 7 e usei também GUID. Responder
16 - 9/11/2011 15:29 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
VITOR RUBIO Fernanda, boa tarde.
Qual é a versão do seu Delphi? Algumas particularidades dos operadores "is" e "as" no sentido interface --> objeto passaram a funcionar apenas no Delphi XE.

Além disso a interface deve obrigatoriamente ter um GUID para que os operadores is e as funcionem com ela.
Responder
17 - 8/11/2011 18:41 - ClubeDelphi - POO - Dominando o uso de Interfaces - Revista Clube Delphi 134
Fernanda Lopes Tenho uma dúvida sobre a Matéria de Interface:

Fui tentar fazer exatamente como é mostrado nas listagens apresentadas para exemplos e dá erro quando tento compilar o código da 'listagem 5' da página 49, na seguinte parte:

-> if (aviao is TAviao) then
begin
ShowMessage('Avião é um TAviao');
(aviao as TAviao).DeslocarSe;
end;

O Delphi apresenta a seguinte mensagem de erro:
Operator not applicable to this operand type

Se alguém puder me ajudar me explicando o porquê disso, agradeço.
Responder
18 - 27/10/2011 19:14 - ClubeDelphi - Usando o Padrão Singleton - Revista ClubeDelphi 133
VITOR RUBIO Corrigi e comentei alguns aspectos do seu singleton. Você pode fazer assim:



unit singleton;

interface

uses sysutils;

type
TSingleton = class
private
FCreationTimeStamp:string;
public
class function GetInstance: Tsingleton;
class function NewInstance: TObject; override;
procedure FreeInstance; override;
function DoSomethingImportant: string;
end;

procedure FreeFirstNilAfter(var Obj); //MeuFreeAndNilBom
procedure FreeFirstNilAfterOneReference(var Obj); //OutroFreeAndNilBom

implementation

var
//Se o Delphi 2007 não suportasse class vars tudo bem colocar esse campo aqui, mas creio que ele suporta:
//consulte os sites:
//http://www.marcocantu.com/md2005/UpdateDelphi2006_ch04.html
//http://hallvards.blogspot.com/2007/05/hack17-virtual-class-variables-part-i.html
//http://edn.embarcadero.com/article/34324
//https://forums.embarcadero.com/thread.jspa?threadID=24246

_Instance: Tsingleton;

//eu aconselho a colocar FCreationTimeStamp como um campo de instância privado pois ele é parte intrinseca da lógica de negócio
//da instância do singleton. Ele não faz sentido fora da classe e não tem porque ser uma variável estática global.
//lembre-se que ele é usado apenas em DoSomethingImportant, que é um método de instância.
//como NewInstance é um método de classe inicialize FCreationTimeStamp apenas no Create.
//se quiser continuar usando no escopo global de implementation use outro prefixo no lugar de F, pois F é para fields de classes.
//usa-lo no NewInstance também é possível como abaixo, mas lembre-se que FCreationTimeStamp é apenas um exemplo que significa uma
//propriedade, valor ou recurso do seu negócio, e DoSomethingImportant é algo importante que só o seu singleton pode fazer.
//FCreationTimeStamp:string;

class function Tsingleton.GetInstance: Tsingleton;
begin
// inherited Create;
// Result := _Instance;

// essa parte pode ficar assim:
Result := inherited Create;
// Lembre que chamar Create é como chamar um atalho "especial" para NewInstance, ou seja, já está jogando _Instance no Result
end;

class function Tsingleton.NewInstance: TObject;
begin
if _Instance = nil then
begin
_Instance := (inherited NewInstance as Tsingleton);
//se quiser continuar sem um construtor atribua o valor a FCreationTimeStamp depois de instanciar, e precedido de _Instance
_Instance.FCreationTimeStamp:= FormatDateTime('ddmmyyyy_hhnnsszzz', now);
end;
Result := _Instance;
end;

function Tsingleton.DoSomethingImportant: string;
begin
Result := 'Instância de ' + Self.ClassName + ' Criada em ' +
FCreationTimeStamp + ' no endereço ' + IntToStr(integer(self));
end;

procedure Tsingleton.FreeInstance;
begin
//destruirá apenas quando for permitido
if _Instance <> nil then
begin
inherited FreeInstance;
_Instance := nil;
end;
end;





procedure FreeFirstNilAfter(var Obj); //MeuFreeAndNilBom
var
Temp: TObject;
begin
Temp := TObject(Obj); //primeiro joga a instancia num objeto temporario
Temp.Free; //invoca free na segunda referência, temporária, que será liberada
Pointer(Obj) := nil; //nulifica a variável por último
end;


procedure FreeFirstNilAfterOneReference(var Obj); //OutroFreeAndNilBom
begin
TObject(Obj).Free; //invoca free
Pointer(Obj) := nil; //nulifica a variável
end;


initialization

finalization
//não se esqueça da seção initilization e finalization para que o
//singleton possa ser de fato destruido
if _Instance <> nil then
begin
FreeFirstNilAfter(_Instance); //funciona
//FreeFirstNilAfterOneReference(_Instance); //funciona
//FreeAndNil(_Instance); //não funciona
//_Instance.Free;
//_Instance := nil;
end;
//FreeAndNil(_Instance); //não funciona
//nunca use FreeAndNil aqui pois freeandnil atribui nil à referência antes
//de efetivamente destruir a instância, o que causaria leak e faria FreeInstance falhar
//use free e depois atribua nil

{
isso é curioso, veja o source de freeandnil:

procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj); //primeiro joga a instancia num objeto temporario
Pointer(Obj) := nil; //nulifica a variável e perde a referencia antes de invocar free
Temp.Free; //invoca free na segunda referência, temporária, que será liberada
end;


como FreeAndNil poderia ser:

procedure FreeFirstNilAfter(var Obj); //MeuFreeAndNilBom
var
Temp: TObject;
begin
Temp := TObject(Obj); //primeiro joga a instancia num objeto temporario
Temp.Free; //invoca free na segunda referência, temporária, que será liberada
Pointer(Obj) := nil; //nulifica a variável por último
end;


ou


procedure FreeFirstNilAfterOneReference(var Obj); //OutroFreeAndNilBom
begin
TObject(Obj).Free; //invoca free
Pointer(Obj) := nil; //nulifica a variável
end;

}



end.

{
Considere o exemplo 5 do artigo, ele pode servir para você:

unit singleton5;

interface

uses sysutils;

type
Tsingleton5 = class
strict private
class var _Instance: Tsingleton5;
class var _PodeDestruir: boolean;
FCreationTimeStamp: string;
class destructor Destroy;
class constructor Create;
public
class function GetInstance: Tsingleton5;
class function NewInstance: TObject; override;
procedure FreeInstance; override;
constructor Create;
function DoSomethingImportant: string;
end;

implementation




class function Tsingleton5.GetInstance: Tsingleton5;
begin
if Tsingleton5._Instance = nil then
Tsingleton5._Instance := TSingleton5.Create;
Result := Tsingleton5._Instance;
end;

class constructor Tsingleton5.Create;
begin
Tsingleton5._PodeDestruir := false;
end;

class destructor Tsingleton5.Destroy;
begin
Tsingleton5._PodeDestruir := true;
if Tsingleton5._Instance <> nil then
Tsingleton5._Instance.Destroy;
end;

class function Tsingleton5.NewInstance: TObject;
begin
if _Instance = nil then
_Instance := (inherited NewInstance as Tsingleton5);
Result := _Instance;
end;

constructor Tsingleton5.Create;
begin
FCreationTimeStamp:= DateTimeToStr(now);
end;

function Tsingleton5.DoSomethingImportant: string;
begin
Result := 'Instância de ' + Self.ClassName + ' Criada em ' +
FCreationTimeStamp + ' no endereço ' + IntToStr(integer(self));
end;

procedure Tsingleton5.FreeInstance;
begin
//destruirá apenas quando for permitido
if _PodeDestruir then
begin
inherited FreeInstance;
_Instance := nil;
end;
end;

end.
}


e usar como no exemplo 5 :)
Responder
19 - 27/10/2011 10:59 - ClubeDelphi - Usando o Padrão Singleton - Revista ClubeDelphi 133
VITOR RUBIO Vagner, bom dia.
Infelizmente não tenho o Delphi 2007 para testar, mas se você acompanhar os exemplos do meu blog verá que é possível criar boas implementações de singleton mesmo no Delphi 7 ou lazarus.

O importante do singleton é ter mecanismos que assegurem sua única instância, que não seja possível criar uma segunda por engano e que ele não cause um leak.

O artigo na Clube Delphi 133 pode ser interpretado como a "parte 5" dessa série sobre singletons, já que usei uma abordagem um pouquinho diferente.

http://blog.vitorrubio.com.br/2010/11/existem-1001-maneiras-de-preparar.html
Responder
20 - 27/10/2011 10:36 - ClubeDelphi - Bancos de Dados Gratuitos - Revista ClubeDelphi 132 - parte 2
VITOR RUBIO Fico feliz com seu feedback. Sinta-se à vontade para perguntar se tiver alguma dúvida. Responder
21 - 27/10/2011 10:32 - ClubeDelphi - Bancos de Dados Gratuitos - Revista ClubeDelphi 132 - parte 2
AUGUSTO LEFEVRE Estou começando a ler a série. Quando terminar direi o que achei.
Por enquanto acho útil.
Responder
22 - 13/10/2011 20:12 - ClubeDelphi - Usando o Padrão Singleton - Revista ClubeDelphi 133
club athletico paulistano Gostei da matéria, parabéns ao Vitor.

Não sei se está conforme os padrões, mas para o Delphi2007 fiz assim.

type
TSingleton = class
public
class function GetInstance: Tsingleton;

class function NewInstance: TObject; override;
procedure FreeInstance; override;

function DoSomethingImportant: string;
end;

implementation
var
_Instance: Tsingleton;
FCreationTimeStamp:string;

class function Tsingleton.GetInstance: Tsingleton;
begin
inherited Create;

Result := _Instance;
end;

class function Tsingleton.NewInstance: TObject;
begin
if _Instance = nil then
begin
FCreationTimeStamp:= FormatDateTime('ddmmyyyy_hhnnsszzz', now);
_Instance := (inherited NewInstance as Tsingleton);
end;

Result := _Instance;
end;

function Tsingleton.DoSomethingImportant: string;
begin
Result := 'Instância de ' + Self.ClassName + ' Criada em ' +
FCreationTimeStamp + ' no endereço ' + IntToStr(integer(self));
end;

procedure Tsingleton.FreeInstance;
begin
//destruirá apenas quando for permitido
if _Instance <> nil then
begin
inherited FreeInstance;
_Instance := nil;
end;
end;


(Vagner)
Responder
23 - 18/9/2011 20:03 - ClubeDelphi - Bancos de Dados Gratuitos - Revista ClubeDelphi 133 - Parte 3
VITOR RUBIO Quando dá a mensagem que falta algum arquivo, dcu ou pas (geralmente pas) é porque o local onde está esse arquivo não está no searching path e no browsing path. Só procurar o diretório onde está o arquivo e adicionar nos dois paths na configuração do Delphi. Responder
24 - 17/9/2011 20:03 - ClubeDelphi - Bancos de Dados Gratuitos - Revista ClubeDelphi 133 - Parte 3
Rodrigo Pereira Barra Pessoal, tinha mandado a dúvida, mas depois de quebrar a cabeça consegui instalar. Eu peguei os nomes dos arquivos que estavam dando problema, e pesquisei a localização exata desses .dcu. Aí adicionei no library e browsing path o caminho exato deles. Aí foi compilando e dando erro em outros. Aí fui fazendo a mesma coisa e deu certo.
Postei pq mais algum sem muita experiência pode precisar.
Responder
25 - 17/9/2011 19:44 - ClubeDelphi - Bancos de Dados Gratuitos - Revista ClubeDelphi 133 - Parte 3
Rodrigo Pereira Barra Vitor artigo muito bom.
Mas preciso de ajuda sua ou de alguém que saiba.
Eu baixei o Zeos7-alpha modificado por você para o Delphi XE, beleza. Aí eu adicionei as librarys e browsing paths. Comecei a compilar os pacotes do group. Os 4 primeiros compilaram beleza. Aí cheguei no ZComponent150.bpl dá erro não compila. dá erros nas linhas dos drivers ( ZDbcAdo, ZDbcMySql,ZDbcPostgreSql,ZDbcInterbase6,ZDbcSqLite, ZDbcOracle,ZDbcASA) e em baixo o erro: F1026 File not found: 'ZDbcAdo.dcu'.
Aí devido á este erro o ZComponentDesign150.bpl também não compila e nem instala.
Se alguém puder me ajudar. Porque estou precisando muito conectar DELPHI XE + MYSQL e não consigo.
Desde já agradeço.
Responder
26 - 27/5/2011 17:57 - ClubeDelphi - Integre projetos .NET e Win32 - Artigo ClubeDelphi 128
CARLOS GONZAGA Vitor, realmente estava usando o mesmo guid. Troquei e gerei novamente e continua dando o erro.
Envie os projetos (.net/win32) p/ seu e-mail
Responder
27 - 27/5/2011 17:06 - ClubeDelphi - Integre projetos .NET e Win32 - Artigo ClubeDelphi 128
VITOR RUBIO Carlos Gonzaga, boa tarde.

Esse erro pode acontecer por vários motivos.
O Assembly feito em Prism ou C# deve ser "com visible", isso você pode ver nas propriedades do projeto ou no assemblyinfo, dependendo da versão de seu visual studio/prism.
Além de ser comvisible o assembly precisa de uma GUID, e a interface dentro do código - fonte (que você implementa) precisa de outra guid, não pode ser igual. É essa guid que deve ser usada pela interface no lado Delphi.
Essa DLL deve ter um strong name, ou seja, deve ser compilada com um arquivo .snk gerado pela ferramenta sn.exe.
Depois de compilar a DLL deve ser registrada no GAC.
Se o problema persistir, por favor me mande o seu fonte e a DLL para eu examinar.
Pode ser problema de ambiente também. Testei no winXP 32 bits.

Responder
28 - 27/5/2011 15:14 - ClubeDelphi - Integre projetos .NET e Win32 - Artigo ClubeDelphi 128
CARLOS GONZAGA Artigo muito interessante pra quem gosta de codificar os recursos extras indente de assistentes.
Mas seguindo o exemplo, na hora da chamada do metodo da o seguinte erro: "OLE error 80131522". O q pode estar acontecendo?

Nota1: o assembly foi registrado normal (delphi 2007/windows 7 32 bits)
Responder
29 - 6/12/2010 17:29 - ClubeDelphi - Design Patterns - Parte 3 - Artigo Clube Delphi 124
Vitor Luiz Rubio Leonardo e Guess Soluções,
Boa tarde.

As duas formas mencionadas por vocês está correta, apenas não coloquei o código para verificar tipo (com o operador as) para simplificar o artigo.
Teoricamente seria possível fazer essa verificação em qualquer ponto que não causasse a inclusão de uma unit a mais no uses gerando acoplamento.

Nesse caso específico um TNossoAdoDataset só seria usado caso o ini estivesse configurado para uso com o ADO, e se o ini estivesse configurado assim então uma fábrica de ADO database seria criada. Como o parâmetro bd não é colocado pelo programador nem pelo usuário, mas é retornado pela fábrica, há uma garantia (fraca, implícita) de que o objeto bd seja realmente um TAdoConnection (caso o ini esteja corretamente configurado) devido a maneira como usamos o conjunto TNossoXXXDataset e a fábrica. 

De qualquer forma, mesmo não sendo possível que a fábrica de TAdoConnection gere um TForm, é possível sim que um programador desavisado utilizasse apenas uma parte do framework e passasse um TForm para o método SetBancoDados. Dessa forma uma verificação de tipo seria uma segurança a mais.

Em última instância um objeto do tipo errado nessa parte dispararia uma mensagem de invalid typecast antes que qualquer problema de corrupção ou perda de dados pudesse ocorrer.

Agradeço pelo feedback.

PS.: Fiquei curioso sobre o uso da metaclasse, poderia compartilhar aqui ou no fórum para um intercâmbio de conhecimento?
Responder
30 - 4/12/2010 11:53 - ClubeDelphi - Design Patterns - Parte 3 - Artigo Clube Delphi 124
GUESS SOLUçõES EM INFORMáTICA LTME ME Caro Leonardo, 

acredito que uma melhor solução, seria criar uma meta classe e utilizá-la como parâmetro de entrada para este método, desta maneira, o tipo de entrada seria fiel ao esperado.

Ou de repente, usar até mesmo o tipo TDataSet como parâmetro.
Responder
31 - 3/12/2010 14:18 - ClubeDelphi - Design Patterns - Parte 3 - Artigo Clube Delphi 124
LEONARDO COELHO BORGES
procedure TNossoAdoDataset.SetBancoDados(bd: TObject);
begin
  if bd <> nil then
  begin
      FDataset.Connection := (bd as TADOConnection);
  end
  else
    raise Exception.Create(Objeto banco de dados nulo!);
end;
 
Conversando com um colega de trabalho, estavamos verificando este método, ele colocou a seguinte situação:
 
   O que acontece se no bd eu passar um TForm em tempo de execução??? O método vai tentar fazer o cast para TADOConnection. 
 
ele colocou a seguinte situação: poderia fazer a verificação do tipo antes do cast.
 
procedure TNossoAdoDataset.SetBancoDados(bd: TObject);
begin
 
  if (bd = nil) then
    raise Exception.Create(Objeto banco de dados nulo!);

  if (db.ClassType = TADOConnection) then
  begin
      FDataset.Connection := (bd as TADOConnection);
  end
  else
    raise Exception.Create(Objeto não é do tipo esperado!);
end;
 
 
Responder
32 - 7/8/2010 02:14 - ClubeDelphi - Strings - Clube Delphi 120
MARLON NARDI Referente a ferramenta encontrei em sua lista de Links:

Responder
33 - 7/8/2010 02:05 - ClubeDelphi - Strings - Clube Delphi 120
MARLON NARDI Vitor,

Li sobre seu artigo, mas não consegui identificar a solução para o problema no qual não migrei minhas Aplicações Desenvolvida no Delphi 2007 para o Delphi 2010.

O problema é este:

Conversei com alguns mais experientes na area, e os mesmos me disseram que eu teria que remover a adicionar novamente os meus Tfields, mas isso vai ser muito trabalhoso, em uma aplicação grande. vou ficar varios dias fazendo isso ate regularizar toda a minha aplicação, não teria uma outra forma para resolver este problema?

Outra coisa, poderia passar o Link da ferramenta, Figura 2 
Statistics Tool
:



Att, Marlon Nardi
Responder

Últimas atualizações deste autor:
.: 22/6/2010 - Easy .net magazine - Visual Studio: Introdução - Easy .net magazine 2
Será dada uma introdução básica sobre a ferramenta, não relacionando com versões anteriores da mesma, mas focando na primeira im...
Atualizado em 6/22/2010 2:02:19 PM
Sobre o autor
Analista de Sistemas Sr. na Editora Revista dos Tribunais. Trabalha com Delphi desde a versão 3. Formado em Processamento de Dados pela FATEC-SP
Estatísticas do Autor:
Número de posts: 20
Características dos posts deste autor:
Conteúdo:
Utilidade:
3 1
 
DevMedia Group - Tel: (21) 3382-5038 - www.devmedia.com.br
Todos os Direitos Reservados a DevMedia Group