Array
(
)

outra dúvida de poo

Vitor^_^
   - 03 fev 2006

considerem as classes:
#Código

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:
#Código
type
TPitBull = class(Tcachorro);

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

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

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

desse jeito funciona normalmente.

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


Massuda
   - 03 fev 2006

A diferença é que usando o as, 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...#Código

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 as 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 as deve funcionar sem problemas.


Vitor^_^
   - 03 fev 2006

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


Michael
   - 03 fev 2006

Typecasts via Tipo(Expressão) só devem ser usados para variáveis e valores.

#Código

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 Massuda disse, vc tem que saber o que está fazendo.

Para fazer casts de classes e interfaces, use sempre que possível o operador as, pelas razões que o colega já explicou.

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

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

[]´s


Vitor^_^
   - 03 fev 2006

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...


Dopi
   - 04 fev 2006

Uma maneira de evitar exceções é fazer um teste usando o IS

#Código


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.