outra dúvida de poo

03/02/2006

considerem as classes:
type
  TCachorro = class(tobject)
  private
    Flatido: string;
    function getLatido: string;
    procedure SetLatido(const Value: string);
  protected
    Mordida: string;
  public
    property Latido: string read getLatido write SetLatido;
  end;

e a descendente:
  type
    TPitBull = class(Tcachorro);

Vamos supor que eu instancie um objeto fcachorro da classe tcachorro:
fcachorro := tcachorro.create;

agora vamos acessar esse cachorro como sendo um TpitBull, fazendo typecast.
se eu fizer
(fcachorro as tpitbull).propriedade 

dá erro de invalid typecast, mas se eu fizer :
tpitbull(fcachorro).propriedade; 

desse jeito funciona normalmente.

qual a diferença de se usar Tipo(variavel) e (Variavel as tipo)?


Vitor^_^

Respostas

03/02/2006

Massuda

A diferença é que usando o [b:aedda8f670]as[/b:aedda8f670], o compilador gera código adicional que verifica se é possível fazer de modo seguro o typecast de uma classe para a outra (gera exceção se não for seguro) enquanto da segunda forma o compilador acredita que você sabe o que está fazendo.

O que é typecast seguro? Vamos supor que...
type 
  TPitBull = class(Tcachorro)
  public
    Manso: Boolean;
  end;
...nesse caso não é seguro fazer o typecast de TCachorro para TPitbull pois TPitbull possui membros/métodos que não existem em TCachorro. O [b:aedda8f670]as[/b:aedda8f670] deve gerar uma exceção; dependendo de diversos fatores, pode ser que você consiga usar o () e forçar o typecast, mas aí estará funcionando por uma feliz coincidência de fatores.

Por outro lado, como TPitbull é derivado de TCachorro, o typecast de TPitbull para TCachorro é seguro pois a classe TPitbull herdou as características de TCachorro; nesse caso o [b:aedda8f670]as[/b:aedda8f670] deve funcionar sem problemas.


Responder Citar

03/02/2006

Vitor^_^

Valew! Isso explica muita coisa que eu ignorei durante muito tempo....


Responder Citar

03/02/2006

Michael

Typecasts via [b:3b19a781bf]Tipo(Expressão)[/b:3b19a781bf] só devem ser usados para variáveis e valores.

var
  I: Integer;
  C: Char;
begin
  I := Integer(´A´); // typecast de valor
  C := Char(I); // typecast de variável
end;


Como um objeto é referenciado através de uma variável, essa forma de typecast tbm funciona, mas como o [b:3b19a781bf]Massuda [/b:3b19a781bf]disse, vc tem que saber o que está fazendo.

Para fazer casts de classes e interfaces, use sempre que possível o operador [b:3b19a781bf]as[/b:3b19a781bf], pelas razões que o colega já explicou.

A segunda maneira utilizada no seu exemplo - [b:3b19a781bf]TPitBull(FCachorro)[/b:3b19a781bf] - deveria gerar uma violação de acesso, pois - novamente o [b:3b19a781bf]Massuda [/b:3b19a781bf]observou bem - as propriedades de [b:3b19a781bf]TPitBull [/b:3b19a781bf]não existem em [b:3b19a781bf]TCachorro[/b:3b19a781bf].

Se rodou sem erros, foi mesmo muita coincidência...

[]´s


Responder Citar

03/02/2006

Vitor^_^

não foi coincidencia, na verdade, quem colocou o campo público Manso: boolean foi o Massuda, aí desse jeito não funcionaria.

no meu caso funcionou porque eu declarei assim:

TPitBull = class(Tcachorro);

ou seja, a classe descendente não tinha nada de diferente, só o nome. Se eu tivesse colocado novos métodos e propriedades aí sim ia dar erro...


Responder Citar

04/02/2006

Dopi

Uma maneira de evitar exceções é fazer um teste usando o [b:3db8978d39]IS[/b:3db8978d39]

if fcachorro is tpitbull then
   tpitbull(fcachorro).manso := true


dessa maneira vc poderia declarar uma váriavel do tipo Tcachorro e instanciar qq descendente de Tchachorro nela (como por exemplo TPitBull)... Quando vc quiser acessar uma propriedade especifica de uma classe filha (que não existe na classe pai)... vc usa o teste com IS para verificar se o Objeto instanciado é realmente daquele tipo... se o for, vc usa o TypeCast para acessar as propriedades publicas exclusivas da classe filha.[/code]


Responder Citar