Qual é a diferença entre polimorfismo dinâmico e estático em Java?

118

Alguém pode fornecer um exemplo simples que explica a diferença entre o polimorfismo dinâmico e estático em Java?

Prabhakar Manthena
fonte
4
As substituições às vezes são chamadas de "polimorfismo estático". Isso estica um pouco as coisas, mas é o que está acontecendo.
dasblinkenlight
@dasblinkenlight obrigado pela informação. existe algum exemplo para isso ??
Prabhakar Manthena
Procure por "sobrecarga de método" e "sobreposição de método".
dasblinkenlight
5
Não entendo como a sobrecarga é o polimorfismo. O polimorfismo é um conceito de objeto. devemos ser capazes de mostrar o objeto B como objeto A. abaixo (resposta) exemplo você mostrou Cachorro como um Animal e, portanto, é polimorfismo. Mas ao sobrecarregar, você está chamando um método diferente, mas com "mesmo nome". Como pode isso ser polimorfismo. Portanto, "vinculação estática" é o termo correto a ser usado, mas o polimorfismo estático não ocorre em caso de sobrecarga.
Punith Raj
@PunithRaj Você provavelmente está se referindo ao polimorfismo de subtipo . Existe outro tipo chamado Ad hoc que se aplica à sobrecarga.
Kelvin

Respostas:

196

Polimorfismo

1. Vinculação estática / vinculação de tempo de compilação / vinculação inicial / sobrecarga de método. (Na mesma classe)

2. Vinculação dinâmica / vinculação em tempo de execução / vinculação tardia / modificação de método. (Em classes diferentes)

exemplo de sobrecarga:

class Calculation {  
  void sum(int a,int b){System.out.println(a+b);}  
  void sum(int a,int b,int c){System.out.println(a+b+c);}  

  public static void main(String args[]) {  
    Calculation obj=new Calculation();  
    obj.sum(10,10,10);  // 30
    obj.sum(20,20);     //40 
  }  
}  

exemplo de substituição:

class Animal {    
   public void move(){
      System.out.println("Animals can move");
   }
}

class Dog extends Animal {

   public void move() {
      System.out.println("Dogs can walk and run");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal a = new Animal(); // Animal reference and object
      Animal b = new Dog(); // Animal reference but Dog object

      a.move();//output: Animals can move

      b.move();//output:Dogs can walk and run
   }
}
KhAn SaAb
fonte
6
Eu sou novo em Java, então apenas curioso qual é o conceito subjacente entre Animal reference but Dog object, por que não podemos usar Dog reference and dog object?
praticamente
3
No exemplo acima, tentei mostrar o conceito de polimorfismo. podemos criar a referência e o objeto da mesma classe, mas não podemos substituir o método. prossiga com a postagem abaixo: stackoverflow.com/questions/12159601/…
KhAn SaAb
a sobrecarga do método é o polimorfismo do tempo de compilação. é da mesma maneira. a sobrecarga do construtor também é o polimorfismo do tempo de compilação?
Gaali Prabhakar
29
  • A sobrecarga de método seria um exemplo de polimorfismo estático

  • enquanto a substituição seria um exemplo de polimorfismo dinâmico.

    Porque, em caso de sobrecarga, em tempo de compilação o compilador sabe qual método vincular à chamada. No entanto, é determinado em tempo de execução para polimorfismo dinâmico

user1374
fonte
17

Polimorfismo dinâmico (tempo de execução) é o polimorfismo existente no tempo de execução. Aqui, o compilador Java não entende qual método é chamado no momento da compilação. Apenas a JVM decide qual método é chamado em tempo de execução. Sobrecarga de método e substituição de método usando métodos de instância são os exemplos de polimorfismo dinâmico.

Por exemplo,

  • Considere um aplicativo que serializa e desserializa diferentes tipos de documentos.

  • Podemos ter 'Documento' como a classe base e diferentes classes de tipo de documento derivadas dela. Por exemplo, XMLDocument, WordDocument, etc.

  • A classe de documento definirá os métodos 'Serialize ()' e 'De-serialize ()' como virtuais e cada classe derivada implementará esses métodos em sua própria maneira, com base no conteúdo real dos documentos.

  • Quando diferentes tipos de documentos precisam ser serializados / desserializados, os objetos do documento serão referenciados pela referência de classe 'Documento' (ou ponteiro) e quando os métodos 'Serialize ()' ou 'De-serialize ()' são chamados nele, versões apropriadas dos métodos virtuais são chamadas.

Polimorfismo estático (tempo de compilação) é o polimorfismo exibido em tempo de compilação. Aqui, o compilador Java sabe qual método é chamado. Sobrecarga de método e substituição de método usando métodos estáticos; substituição de métodos usando métodos privados ou finais são exemplos de polimorfismo estático

Por exemplo,

  • Um objeto funcionário pode ter dois métodos print (), um sem argumentos e outro com uma string de prefixo para ser exibida junto com os dados do funcionário.

  • Dadas essas interfaces, quando o método print () é chamado sem nenhum argumento, o compilador, observando os argumentos da função, sabe qual função deve ser chamada e gera o código-objeto de acordo.

Para obter mais detalhes, leia "O que é polimorfismo" (Google it).

rachana
fonte
2
Esta resposta está cheia de erros: (1) A sobrecarga do método não é polimorfismo dinâmico. É polimorfismo estático. (2) Os métodos estáticos nunca são sobrescritos, eles são ocultos / sombreados. (3) Os métodos privados não são "substituídos". Eles nunca são herdados em primeiro lugar.
John Red
14

Vinculação refere-se ao link entre a chamada do método e a definição do método.

Esta imagem mostra claramente o que é obrigatório.

obrigatório

Nesta figura, a chamada “a1.methodOne ()” é vinculada à definição do methodOne () correspondente e a chamada “a1.methodTwo ()” é vinculada à definição do methodTwo () correspondente.

Para cada chamada de método, deve haver uma definição de método adequada. Esta é uma regra em java. Se o compilador não vê a definição de método apropriada para cada chamada de método, ele gera um erro.

Agora, vamos à vinculação estática e à vinculação dinâmica em java.

Vinculação estática em Java:

A vinculação estática é uma vinculação que ocorre durante a compilação. Também é chamado de vinculação inicial porque a vinculação acontece antes de um programa realmente ser executado

.

A ligação estática pode ser demonstrada como na imagem abaixo.

insira a descrição da imagem aqui

Nesta figura, 'a1' é uma variável de referência do tipo Classe A apontando para o objeto da classe A. 'a2' também é uma variável de referência do tipo classe A, mas apontando para o objeto da Classe B.

Durante a compilação, durante a vinculação, o compilador não verifica o tipo de objeto para o qual uma determinada variável de referência está apontando. Ele apenas verifica o tipo de variável de referência através da qual um método é chamado e verifica se existe uma definição de método para ele nesse tipo.

Por exemplo, para a chamada do método “a1.method ()” na imagem acima, o compilador verifica se existe definição de método para o método () na Classe A. Porque 'a1 ′ é do tipo Classe A. Da mesma forma, para chamada de método “a2.method ()”, ele verifica se existe definição de método para method () na Classe A. Porque 'a2' também é do tipo Classe A. Ele não verifica para qual objeto 'a1' e 'a2' estão apontando. Esse tipo de vinculação é denominado vinculação estática.

Vinculação dinâmica em Java:

A vinculação dinâmica é uma vinculação que ocorre durante o tempo de execução. Também é chamado de vinculação tardia porque a vinculação ocorre quando o programa está realmente em execução.

Durante o tempo de execução, os objetos reais são usados ​​para vinculação. Por exemplo, para a chamada “a1.method ()” na imagem acima, o método () do objeto real para o qual 'a1' está apontando será chamado. Para a chamada de “a2.method ()”, o método () do objeto real para o qual 'a2' está apontando será chamado. Esse tipo de vinculação é denominado vinculação dinâmica.

A ligação dinâmica do exemplo acima pode ser demonstrada como abaixo.

insira a descrição da imagem aqui

Referência static-binding-and-dynamic-binding-in-java

Elsayed
fonte
melhor do que antes.
AnBisw
8

Polimorfismo: Polimorfismo é a capacidade de um objeto de assumir várias formas. O uso mais comum de polimorfismo em OOP ocorre quando uma referência de classe pai é usada para se referir a um objeto de classe filho.

Polimorfismo de ligação dinâmica / tempo de execução:

Polimorfismo de tempo de execução, também conhecido como substituição de método. Neste mecanismo pelo qual uma chamada para uma função substituída é resolvida em um tempo de execução.

public class DynamicBindingTest {

    public static void main(String args[]) {
        Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
        vehicle.start();       //Car's start called because start() is overridden method
    }
}

class Vehicle {

    public void start() {
        System.out.println("Inside start method of Vehicle");
    }
}

class Car extends Vehicle {

    @Override
    public void start() {
        System.out.println("Inside start method of Car");
    }
}

Resultado:

Método de partida interno do carro

Polimorfismo de ligação estática / tempo de compilação:

Qual método deve ser chamado é decidido apenas em tempo de compilação.

public class StaticBindingTest {

    public static void main(String args[])  {
       Collection c = new HashSet();
       StaticBindingTest et = new StaticBindingTest();
       et.sort(c);

    }

    //overloaded method takes Collection argument
    public Collection sort(Collection c){
        System.out.println("Inside Collection sort method");
        return c;
    }


   //another overloaded method which takes HashSet argument which is sub class
    public Collection sort(HashSet hs){
        System.out.println("Inside HashSet sort method");
        return hs;
    }

}

Resultado: Método de classificação interna da coleção

Loknath
fonte
8

sobrecarga de método é um exemplo de tempo de compilação / polimorfismo estático porque a vinculação de método entre a chamada do método e a definição do método acontece em tempo de compilação e depende da referência da classe (referência criada em tempo de compilação e vai para a pilha).

a sobreposição de método é um exemplo de polimorfismo dinâmico / em tempo de execução porque a vinculação de método entre a chamada e a definição do método ocorre em tempo de execução e depende do objeto da classe (objeto criado em tempo de execução e vai para o heap).

Sujith PS
fonte
* (o objeto é criado em tempo de execução e vai para o heap), deve ser executado em tempo de execução
Conheça
7

Em termos simples :

Polimorfismo estático : o mesmo nome de método está sobrecarregado com diferentes tipos ou números de parâmetros na mesma classe (assinatura diferente). A chamada do método direcionado é resolvida em tempo de compilação.

Polimorfismo dinâmico : o mesmo método é sobrescrito com a mesma assinatura em classes diferentes . O tipo de objeto no qual o método está sendo chamado não é conhecido em tempo de compilação, mas será decidido em tempo de execução.

Geralmente, a sobrecarga não é considerada polimorfismo.

Da página do tutorial Java :

As subclasses de uma classe podem definir seus próprios comportamentos exclusivos e ainda compartilhar algumas das mesmas funcionalidades da classe pai

Ravindra babu
fonte
Generally overloading won't be considered as polymorphism.você pode elaborar sobre este ponto.
primo de
1
Vinculação dinâmica e substituição são pontos marcantes para o polimorfismo
Ravindra babu,
5

A sobrecarga de método é conhecida como polimorfismo estático e também conhecida como polimorfismo em tempo de compilação ou vinculação estática porque as chamadas de método sobrecarregadas são resolvidas em tempo de compilação pelo compilador com base na lista de argumentos e na referência na qual estamos chamando o método.

E método de substituição é conhecido como dinâmico Polimorfismo ou simples Polimorfismo ou Runtime Método de despacho ou vinculação dinâmica porque substituído chamada de método são resolvidos em tempo de execução.

Para entender por que isso é por isso vamos dar um exemplo de Mammale Humanclasse

class Mammal {
    public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}

class Human extends Mammal {

    @Override
    public void speak() { System.out.println("Hello"); }

    public void speak(String language) {
        if (language.equals("Hindi")) System.out.println("Namaste");
        else System.out.println("Hello");
    }

}

Eu incluí a saída, bem como o bytecode nas linhas de código abaixo

Mammal anyMammal = new Mammal();
anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V

E olhando para o código acima, podemos ver que os bytecodes de humanMammal.speak (), human.speak () e human.speak ("Hindi") são totalmente diferentes porque o compilador é capaz de diferenciar entre eles com base na lista de argumentos e referência de classe. E é por isso que a sobrecarga de método é conhecida como polimorfismo estático .

Mas o bytecode para anyMammal.speak () e humanMammal.speak () é o mesmo porque, de acordo com o compilador, ambos os métodos são chamados na referência Mammal, mas a saída para ambas as chamadas de método é diferente porque no tempo de execução JVM sabe qual objeto uma referência está mantendo e chamadas JVM o método no objeto e é por isso que a Substituição de Método é conhecida como Polimorfismo Dinâmico.

Portanto, pelo código e bytecode acima, é claro que durante a fase de compilação o método de chamada é considerado a partir do tipo de referência. Mas em tempo de execução o método será chamado a partir do objeto que a referência está segurando.

Se você quiser saber mais sobre isso, pode ler mais em Como a JVM trata a sobrecarga e a substituição de métodos internamente .

Naresh Joshi
fonte
3

Polimorfismo estático: é onde a decisão de decidir qual método realizar, é determinada durante o tempo de compilação. A sobrecarga do método pode ser um exemplo disso.

Polimorfismo Dinâmico: é onde a decisão de escolher qual método executar, é definida durante o tempo de execução. A substituição de método pode ser um exemplo disso.

Kulasangar
fonte
3

Polimorfismo se refere à capacidade de um objeto de se comportar de maneira diferente para o mesmo gatilho.

Polimorfismo estático (polimorfismo em tempo de compilação)

  • O polimorfismo estático decide qual método executar durante o tempo de compilação.
  • A sobrecarga do método é um exemplo de polimorfismo estático, e é necessário que ocorra o polimorfismo estático.
  • Polimorfismo estático obtido por meio de ligação estática.
  • O polimorfismo estático ocorre na mesma classe.
  • A atribuição de objetos não é necessária para o polimorfismo estático.
  • Herança não envolvida para polimorfismo estático.

Polimorfismo dinâmico (polimorfismo de tempo de execução)

  • O polimorfismo dinâmico decide qual método executar em tempo de execução.
  • Substituição de método é um exemplo de polimorfismo dinâmico, e é necessário que ocorra o polimorfismo dinâmico.
  • Polimorfismo dinâmico obtido por meio de ligação dinâmica.
  • O polimorfismo dinâmico ocorre entre classes diferentes.
  • É necessário quando um objeto de subclasse é atribuído a um objeto de superclasse para polimorfismo dinâmico.
  • Herança envolvida para polimorfismo dinâmico.
Saveendra Ekanayake
fonte
1

Polimorfismo de tempo de compilação (Static Binding / Early Binding): No polimorfismo estático, se chamarmos um método em nosso código, então qual definição desse método deve ser chamada realmente é resolvida apenas no tempo de compilação.

(ou)

Em tempo de compilação, Java sabe qual método invocar verificando as assinaturas do método. Portanto, isso é chamado de polimorfismo em tempo de compilação ou ligação estática.

Polimorfismo dinâmico (Late Binding / Runtime Polymorphism): Em tempo de execução, o Java espera até o tempo de execução para determinar qual objeto está realmente sendo apontado pela referência. A resolução do método foi tomada em tempo de execução, por isso chamamos de polimorfismo de tempo de execução.

Pavan Reddy
fonte
1

Considere o código abaixo:

public class X
{
    public void methodA() // Base class method
    {
        System.out.println ("hello, I'm methodA of class X");
    }
}

public class Y extends X
{
    public void methodA() // Derived Class method
    {
        System.out.println ("hello, I'm methodA of class Y");
    }
}
public class Z
{
public static void main (String args []) {

    //this takes input from the user during runtime
    System.out.println("Enter x or y");
    Scanner scanner = new Scanner(System.in);
    String value= scanner.nextLine();

    X obj1 = null;
    if(value.equals("x"))
        obj1 = new X(); // Reference and object X
    else if(value.equals("y"))
        obj2 = new Y(); // X reference but Y object
    else
        System.out.println("Invalid param value");

    obj1.methodA();
}
}

Agora, olhando para o código, você nunca pode dizer qual implementação de methodA () será executada, porque depende de qual valor o usuário dá durante o tempo de execução. Portanto, só é decidido em tempo de execução qual método será chamado. Conseqüentemente, polimorfismo de tempo de execução.

user2048204
fonte
0

A sobrecarga de método é um polimorfismo em tempo de compilação, vamos dar um exemplo para entender o conceito.

class Person                                            //person.java file
{
    public static void main ( String[] args )
    {
      Eat e = new Eat();
       e.eat(noodle);                                //line 6
    }

   void eat (Noodles n)      //Noodles is a object    line 8                     
   {

   }
   void eat ( Pizza p)           //Pizza is a object
  {

  }

}

Neste exemplo, Pessoa tem um método de comer que representa que ela pode comer Pizza ou Macarrão. Que o método eat está sobrecarregado quando compilamos este Person.java o compilador resolve a chamada do método "e.eat (noodles) [que está na linha 6] com a definição do método especificada na linha 8, ou seja, é o método que leva macarrão como parâmetro e todo o processo é feito pelo Compilador, portanto é Polimorfismo em tempo de compilação O processo de substituição da chamada do método pela definição do método é chamado de ligação, neste caso, é feito pelo compilador, por isso é chamado de ligação inicial.

Manoj Gururaj
fonte
0

Seguindo a resposta de Naresh, o polimorfismo dinâmico é apenas 'dinâmico' em Java por causa da presença da máquina virtual e sua capacidade de interpretar o código em tempo de execução, em vez do código rodando nativamente.

Em C ++, isso deve ser resolvido em tempo de compilação se estiver sendo compilado para um binário nativo usando gcc, obviamente; no entanto, o salto e a conversão do tempo de execução na tabela virtual ainda são chamados de 'pesquisa' ou 'dinâmica'. Se C herdar B e você declarar B* b = new C(); b->method1();, b será resolvido pelo compilador para apontar para um objeto B dentro de C (para uma classe simples herda uma situação de classe, o objeto B dentro de C e C começarão no mesmo endereço de memória, então nada precisa ser feito; ele estará apontando para o vptr que ambos usam). Se C herdar B e A, a tabela de função virtual do objeto A dentro da entrada C para o método1 terá uma conversão que deslocará o ponteiro para o início do objeto C que encapsula e o passará para o A :: método1 real () no segmento de texto que C substituiu. ParaC* c = new C(); c->method1(), c estará apontando para o objeto C externo já e o ponteiro será passado para C :: method1 () no segmento de texto. Consulte: http://www.programmersought.com/article/2572545946/

Em java, for B b = new C(); b.method1();, a máquina virtual é capaz de verificar dinamicamente o tipo do objeto pareado com be pode passar o ponteiro correto e chamar o método correto. A etapa extra da máquina virtual elimina a necessidade de tabelas de funções virtuais ou o tipo sendo resolvido em tempo de compilação, mesmo quando poderia ser conhecido em tempo de compilação. É apenas uma maneira diferente de fazer isso, o que faz sentido quando uma máquina virtual está envolvida e o código é compilado apenas em bytecode.

Lewis Kelsey
fonte