Anteriormente usamos classes para criar novos tipos e usamos herança para facilitar nosso processo de criação de classes. Nesta palestra vou mergulhar nos tipos e apresentar o conceito de polimorfismo.
verificação de tipo
Quaisquer variáveis e referências em Java só podem ser usadas após passar uma declaração de tipo. Vimos antes que dados de objetos, dados de classes, parâmetros de métodos, valores de retorno de métodos e variáveis automáticas dentro de métodos precisam declarar seus tipos. Java é uma linguagem fortemente tipada, que verifica tipos. Se usarmos o tipo errado, isso causará erros.
O tipo não corresponde, a fofura é inválida
Por exemplo, na classe Test abaixo, atribuímos um objeto da classe Cup a uma referência da classe Person:
public class Test{ public static void main(String[] args) { Human aPerson; aPerson = new Cup(); } /** * acessador */ public int getHeight() { return this.height } /** * mutador */ public void growHeight(int h) { this.height = this.height + h } private; int height;}class Cup { public void addWater(int w) { this.water = this.water + w } public void drinkWater(int w) { this.water = this.water - w; ;}
javac retornará:
encontrado: Cuprequired: Human aPerson = new Cup();
Conversão de tipo básico
Java pode realizar conversão de tipo em variáveis de tipos básicos. Diferentes tipos básicos têm diferentes comprimentos e faixas de armazenamento. Se convertermos de um tipo de alta precisão para um tipo de baixa precisão, como a conversão de float para int, poderemos perder informações. Essa conversão é chamada de conversão restritiva. Neste caso, precisamos declarar explicitamente a conversão de tipo, como:
public class Test{ public static void main(String[] args) { int a; a = (int) 1.23;
Se convertermos de um tipo de baixa precisão para um tipo de alta precisão, não haverá preocupação com a perda de informações. Tal transformação é chamada de conversão ampliada. Não precisamos exigir explicitamente a conversão de tipo, Java pode fazer isso automaticamente:
public class Test{ public static void main(String[] args) { int a = 3;
Conversão de tipo básico
upcast e polimorfismo
Em Java, as referências também podem ser convertidas em tipo, mas há restrições.
Podemos converter uma referência de classe derivada em sua referência de classe base, que é chamada de conversão upcast ou relaxada. A seguinte classe BrokenCup herda da classe Cup e substitui os métodos addWater() e drinkWater() originais na classe Cup:
public class Test{ public static void main(String[] args) { Cup aCup; // ligação do método }}class Cup { public; void addWater(int w) { this.water = this.water + w } public void drinkWater(int w) { this.water = this.water - w; } private int water = 0;} class BrokenCup estende Cup{ public void addWater(int w) { System.out.println("merda, copo quebrado" } public void drinkWater(int w) { System.out. println("om...num..., sem água dentro");
Resultados da execução do programa:
merda, copo quebrado
Como você pode ver acima, sem quaisquer instruções explícitas, atribuímos a referência de classe derivada aBrokenCup à sua referência de classe base aCup. A conversão de tipo será feita automaticamente por Java.
Em seguida, chamamos o método addWater() de aCup (que declaramos ser do tipo Cup). Embora aCup seja uma referência do tipo Cup, na verdade ele chama o método addWater() de BrokenCup! Em outras palavras, mesmo se afrouxarmos o tipo de referência para sua classe base por meio de upcast, Java ainda poderá identificar corretamente o tipo do próprio objeto e chamar o método correto. Java pode identificar o verdadeiro tipo de um objeto com base na situação atual. Isso é chamado de polimorfismo. O polimorfismo é um aspecto importante da orientação a objetos.
O polimorfismo é um mecanismo suportado por Java e também é um importante conceito orientado a objetos. Isto levanta uma questão taxonômica sobre se os objetos da subclasse realmente “são” objetos da classe pai. Por exemplo, um pássaro também é um animal; um carro também deve ser um meio de transporte. Java nos diz que um objeto de classe derivada pode ser usado como um objeto de classe base, e Java lidará com essa situação corretamente.
Por exemplo, o seguinte relacionamento de herança:
Podemos dizer que bebemos água de um copo. Na verdade, o significado específico da ação da água potável mudará muito na classe derivada. Por exemplo, beber água através de um canudo e beber água de um copo quebrado são muito diferentes, embora todos falemos sobre “água potável” de forma abstrata. Claro, podemos programar separadamente para cada classe derivada e chamar diferentes métodos drinkWater. No entanto, como programadores, podemos programar uma xícara e chamar o método drinkWater() de Cup, independentemente do tipo de xícara derivada da xícara. Java chamará o método correto correspondente, como podemos ver no programa acima.
Olhando para um exemplo mais significativo, adicionamos um método drink() à classe Human. Este método recebe um objeto cup e um número inteiro como parâmetros. Os números inteiros representam a quantidade de água a beber:
public class Test{ public static void main(String[] args) { Human guest = new BrokenCup hisCup = new BrokenCup(); , int w) { aCup.drinkWater(w);
Resultados da execução do programa:
merda, sem água dentro
Na definição de drink() da classe Human, exigimos que o primeiro parâmetro seja uma referência do tipo Cup. Mas na aplicação real (classe Test), o objeto de classe derivado BrokenCup de Cup é usado. Na verdade, isso transfere hisCup para a classe Cup e o passa para o método drink(). No método, chamamos o método drinkWater(). Java descobriu que esse objeto era na verdade um objeto BrokenCup, então ele chamou o método correspondente de BrokenCup.
abatido
Podemos fazer downcast de uma referência de classe base para uma referência de classe derivada, mas o objeto apontado pela referência de classe base já é o objeto de classe derivada a ser downcast. Por exemplo, o hisCup acima pode ser transformado para cima em uma referência de classe Cup e depois transformado para baixo em uma referência de classe BrokenCup.
Tipo de objeto
Em Java, todas as classes têm, na verdade, um ancestral de herança comum, que é a classe Object. A classe Object fornece alguns métodos, como toString(). Podemos substituir esses métodos em nossa própria definição de classe.
Objeto: ancestral
Podemos escrever um programa que opere objetos Object e passe qualquer objeto para o programa por meio de upcast.
Irei me aprofundar na classe Object mais tarde.
(A implementação do polimorfismo depende do suporte RTTI. Entrarei em mais detalhes posteriormente.)
Resumir
Conversão de tipo básico
polimorfismo
abatido
Objeto