Polimorfismo em Java é um conceito pelo qual podemos realizar um ação única de maneiras diferentes . O polimorfismo é derivado de 2 palavras gregas: poli e morfos. A palavra 'poli' significa muitos e 'morfos' significa formas. Portanto, polimorfismo significa muitas formas.
Existem dois tipos de polimorfismo em Java: polimorfismo em tempo de compilação e polimorfismo em tempo de execução. Podemos realizar polimorfismo em java por sobrecarga e substituição de método.
Se você sobrecarregar um método estático em Java, será um exemplo de polimorfismo em tempo de compilação. Aqui, focaremos no polimorfismo de tempo de execução em java.
Polimorfismo de tempo de execução em Java
Polimorfismo de tempo de execução ou Envio de Método Dinâmico é um processo no qual uma chamada para um método substituído é resolvida em tempo de execução, e não em tempo de compilação.
Neste processo, um método substituído é chamado através da variável de referência de uma superclasse. A determinação do método a ser chamado é baseada no objeto ao qual a variável de referência se refere.
Vamos primeiro entender o upcasting antes do polimorfismo em tempo de execução.
Upcasting
Se a variável de referência da classe Parent se referir ao objeto da classe Child, isso é conhecido como upcasting. Por exemplo:
class A{} class B extends A{}
A a=new B();//upcasting
Para upcasting, podemos usar a variável de referência do tipo de classe ou um tipo de interface. Por exemplo:
interface I{} class A{} class B extends A implements I{}
Aqui, a relação da classe B seria:
B IS-A A B IS-A I B IS-A Object
Como Object é a classe raiz de todas as classes em Java, podemos escrever B IS-A Object.
Exemplo de polimorfismo de tempo de execução Java
Neste exemplo, estamos criando duas classes Bike e Splendor. A classe Splendor estende a classe Bike e substitui seu método run(). Estamos chamando o método run pela variável de referência da classe Parent. Como se refere ao objeto da subclasse e o método da subclasse substitui o método da classe Parent, o método da subclasse é invocado em tempo de execução.
python classificando tuplas
Como a invocação do método é determinada pela JVM e não pelo compilador, isso é conhecido como polimorfismo de tempo de execução.
class Bike{ void run(){System.out.println('running');} } class Splendor extends Bike{ void run(){System.out.println('running safely with 60km');} public static void main(String args[]){ Bike b = new Splendor();//upcasting b.run(); } }Teste agora
Saída:
o que é hibernar
running safely with 60km.
Exemplo de polimorfismo de tempo de execução Java: banco
Considere um cenário onde Bank é uma classe que fornece um método para obter a taxa de juros. No entanto, a taxa de juros pode variar de acordo com os bancos. Por exemplo, os bancos SBI, ICICI e AXIS oferecem taxas de juros de 8,4%, 7,3% e 9,7%.
Nota: Este exemplo também é fornecido na substituição de método, mas não houve upcasting.
class Bank{ float getRateOfInterest(){return 0;} } class SBI extends Bank{ float getRateOfInterest(){return 8.4f;} } class ICICI extends Bank{ float getRateOfInterest(){return 7.3f;} } class AXIS extends Bank{ float getRateOfInterest(){return 9.7f;} } class TestPolymorphism{ public static void main(String args[]){ Bank b; b=new SBI(); System.out.println('SBI Rate of Interest: '+b.getRateOfInterest()); b=new ICICI(); System.out.println('ICICI Rate of Interest: '+b.getRateOfInterest()); b=new AXIS(); System.out.println('AXIS Rate of Interest: '+b.getRateOfInterest()); } }Teste agora
Saída:
SBI Rate of Interest: 8.4 ICICI Rate of Interest: 7.3 AXIS Rate of Interest: 9.7
Exemplo de polimorfismo de tempo de execução Java: forma
class Shape{ void draw(){System.out.println('drawing...');} } class Rectangle extends Shape{ void draw(){System.out.println('drawing rectangle...');} } class Circle extends Shape{ void draw(){System.out.println('drawing circle...');} } class Triangle extends Shape{ void draw(){System.out.println('drawing triangle...');} } class TestPolymorphism2{ public static void main(String args[]){ Shape s; s=new Rectangle(); s.draw(); s=new Circle(); s.draw(); s=new Triangle(); s.draw(); } }Teste agora
Saída:
drawing rectangle... drawing circle... drawing triangle...
Exemplo de polimorfismo de tempo de execução Java: Animal
class Animal{ void eat(){System.out.println('eating...');} } class Dog extends Animal{ void eat(){System.out.println('eating bread...');} } class Cat extends Animal{ void eat(){System.out.println('eating rat...');} } class Lion extends Animal{ void eat(){System.out.println('eating meat...');} } class TestPolymorphism3{ public static void main(String[] args){ Animal a; a=new Dog(); a.eat(); a=new Cat(); a.eat(); a=new Lion(); a.eat(); }}Teste agora
Saída:
eating bread... eating rat... eating meat...
Polimorfismo Java Runtime com membro de dados
Um método é substituído, não os membros dos dados, portanto, o polimorfismo de tempo de execução não pode ser alcançado pelos membros dos dados.
No exemplo abaixo, ambas as classes possuem um limite de velocidade de membro de dados. Estamos acessando o membro de dados pela variável de referência da classe Parent que se refere ao objeto da subclasse. Como estamos acessando o membro de dados que não é substituído, ele sempre acessará o membro de dados da classe Parent.
Regra: O polimorfismo de tempo de execução não pode ser alcançado por membros de dados.
class Bike{ int speedlimit=90; } class Honda3 extends Bike{ int speedlimit=150; public static void main(String args[]){ Bike obj=new Honda3(); System.out.println(obj.speedlimit);//90 } }Teste agora
Saída:
90
Polimorfismo Java Runtime com herança multinível
Vamos ver o exemplo simples de Polimorfismo de Tempo de Execução com herança multinível.
class Animal{ void eat(){System.out.println('eating');} } class Dog extends Animal{ void eat(){System.out.println('eating fruits');} } class BabyDog extends Dog{ void eat(){System.out.println('drinking milk');} public static void main(String args[]){ Animal a1,a2,a3; a1=new Animal(); a2=new Dog(); a3=new BabyDog(); a1.eat(); a2.eat(); a3.eat(); } }Teste agora
Saída:
eating eating fruits drinking Milk
Experimente a saída
class Animal{ void eat(){System.out.println('animal is eating...');} } class Dog extends Animal{ void eat(){System.out.println('dog is eating...');} } class BabyDog1 extends Dog{ public static void main(String args[]){ Animal a=new BabyDog1(); a.eat(); }}Teste agora
Saída:
Dog is eating
Como BabyDog não está substituindo o método eat(), o método eat() da classe Dog é invocado.