Hoje vamos recordar os conceitos de downcasting e upcasting relacionados com a herança na linguagem C#. |
A classe filha ou subclasse é um tipo especializado da classe pai ou superclasse que é um tipo geral.
Vamos considerar uma classe Forma como sendo a classe pai e a classe Circulo como sendo a classe Filha definidas com o código abaixo:
Classe Forma -> classe pai -> classe geral | Classe Circulo -> classe filha -> classe especializada |
public class Forma { public virtual void Desenhar() { Console.WriteLine("Forma"); } }
|
public class Circulo : Forma { public override void Desenhar() { Console.WriteLine("Desenhar Circulo"); } public void PintarCirculo() { Console.WriteLine("Pintando o círculo"); } } |
Neste contexto o que vem a ser UpCasting e DownCasting ?
1- UpCasting
A operação de UpCasting converte um objeto de um tipo especializado (classe filha) para um tipo mais geral (classe base)
Podemos entender o upcasting como a atribuição de objeto de uma classe filha para uma referência de uma classe base.
Esta operação é implícita e não é preciso ser feita de forma explicita, sendo sempre possível de ser realizada.
static void
Main(string[] args) { Forma circulo = new Circulo(); circulo.Desenhar(); } |
Podemos ainda fazer assim:
private
static void UpCasting() { Circulo circulo = new Circulo(); Forma f = circulo; Console.WriteLine(f == circulo); f.Desenhar(); } |
Note que embora f e circulo se refiram ao mesmo objeto , f tem uma visão mais restrita deste objeto pois pode acessar somente o método Desenhar.
A variável f é do tipo Forma mesmo se referindo a um objeto do tipo Circulo e por isso não acessa o método PintarCirculo().
Para poder acessar o método PintarCirculo() da classe Circulo temos que fazer o DownCast de Forma para Circulo.
2- DownCasting
A operação de DownCasting converte um objeto de um tipo geral (classe base) para um tipo mais especializado (classe filha).
Podemos entender o downcasting como a atribuição de um objeto da classe base para um objeto da classe derivada.
A operação de downcast deve ser feita de forma explícita pois pode falhar e lançar uma exceção, ou seja, é uma operação que nem sempre é possível de ser realizada.
private static void DownCasting()
{
Circulo circulo = new Circulo();
Forma f = circulo; //upcasting -> implicita
Circulo c = (Circulo)f; //downcast -> explicita
c.PintarCirculo();
c.Desenhar();
Console.WriteLine(c == f);
Console.WriteLine(c == circulo);
}
|
Foi feito o downcast da variável f que é do tipo Forma para Circulo.
Note que a variável c referencia tanto a variável f como a variavel circulo ou seja temos a mesma referência.
Assim a instância c pode acessar o método PintarCirculo() e também Desenhar().
Se o downcast falhar vai ocorrer uma exceção do tipo InvalidCastException.
Usando o operador as
O operador as é usado para executar a conversão entre tipos de referência compatíveis ou tipos anuláveis. Este operador retorna o objeto quando eles são compatíveis com o tipo especificado e retorna nulo se a conversão não for possível em vez de gerar uma exceção.
Assim ele realiza uma operação de downcast mas ao invés de lançar uma exceção avalia o resultado para null.
private static void DownCasting_As()
{
Forma f = new Forma();
Circulo c = f as Circulo; //c será igual a null
if (c != null)
{
c.PintarCirculo();
}
else
{
Console.WriteLine("Operação de downcast inválida (as)");
}
}
|
Usando o operador as para realizar o downcast vai retornar null se a operação falhar.
Assim podemos verificar se o resultado for diferente de null antes de tentar usar o objeto.
Usando o operador is
O operador is é usado para verificar se o tipo de um objeto é compatível com o tipo especificado ou não; ele retorna true se o objeto especificado for do mesmo tipo, caso contrário, retorne false. Ele também retorna false para objetos nulos.
Assim podemos usar o operador is para verificar se uma conversão de referência será bem sucedida ou não.
private static void DownCasting_Is()
{
Circulo circulo = new Circulo();
Forma f = circulo; //upcasting -> implicita
if (f is Circulo) //verifica se o downcast é possível
{
((Circulo)f).PintarCirculo();
}
else
{
Console.WriteLine("Operação de downcast inválida (is)");
}
}
|
Observe que verificamos se o tipo f é compatível com o tipo Circulo, e, se for, vai retornar true , e, então poderemos acessar o método PintarCirculo(). Como a operação é valida o método PintarCirculo será executado.
Apenas para concluir vamos listar as diferenças entre os operadores is e as :
- O operador
is é usado para
verificar se o tipo de um objeto (em tempo de
execução) é compatível com o tipo especificado ou
não, enquanto o operador as
é usado para executar a conversão entre tipos de
referência compatíveis ou tipos anuláveis.
- O operador is é do tipo
booleano, enquanto o operador as não é do tipo booleano.
- O operador is retorna
true se o objeto especificado for do mesmo tipo,
enquanto o operador as retorna o objeto quando eles são
compatíveis com o tipo especificado.
- O operador is retorna
false se o objeto especificado não for do mesmo tipo,
enquanto operador as retorna null se a conversão não for
possível.
- O operador is é usado
apenas para conversões de referência, boxe e unboxing,
enquanto o operador as é usado apenas para conversões
anuláveis, de referência e boxing
Pegue o código do projeto aqui: UpDownCast.zip
"Mas Deus
escolheu as coisas loucas deste mundo para confundir as sábias; e Deus escolheu
as coisas fracas deste mundo para confundir as fortes;
E Deus escolheu as coisas vis deste mundo, e as desprezíveis, e as que não são,
para aniquilar as que são;
Para que nenhuma carne se glorie perante ele."
1 Coríntios 1:27-29
Referências:
VB .NET - Lendo Arquivos Binários - BinaryReader - Macoratti ...
Tratamento de arquivos - Questões práticas - Macoratti.net
C# - Copiando Arquivos - Macoratti
C# - Localizando linhas em um arquivo texto - Macoratti.net
VB .NET - Armazenando um objeto serializado em um arquivo
C# - Programa para Loja de Instrumentos Musicais - Macoratti ...
C# - Lendo e gravando dados binários no SQL ... - Macoratti