Você pode escrever funções / métodos virtuais em Java?


165

É possível escrever métodos virtuais em Java, como se faria em C ++?

Ou existe uma abordagem Java apropriada que você possa implementar que produz um comportamento semelhante? Poderia, por favor, ter alguns exemplos?

Respostas:


305

Da wikipedia

Em Java , todos os métodos não estáticos são, por padrão, " funções virtuais " . Somente os métodos marcados com a palavra - chave final , que não podem ser substituídos, juntamente com os métodos privados , que não são herdados, não são virtuais .


3
Aqui está uma das respostas de Jon Skeet .
Quazi Irfan

Gostaria de saber se é realmente verdade, porque, pelo que li, em Java, o despacho de método dinâmico ocorre apenas para o objeto em que o método é chamado - conforme explicado aqui; portanto, o exemplo que explica funções virtuais para C ++ aqui não é válido para java.
Broccoli

@QuaziIrfan Essa é a diferença entre Java e C #.
Sreekanth Karumanaghat 24/12/19

101

Você pode escrever funções virtuais em Java?

Sim. De fato, todos os métodos de instância em Java são virtuais por padrão. Apenas certos métodos não são virtuais:

  • Métodos de classe (porque normalmente cada instância contém informações como um ponteiro para uma vtable sobre seus métodos específicos, mas nenhuma instância está disponível aqui).
  • Métodos de instância privada (como nenhuma outra classe pode acessar o método, a instância de chamada sempre tem o tipo da própria classe de definição e, portanto, é inequivocamente conhecida em tempo de compilação).

aqui estão alguns exemplos:

Funções virtuais "normais"

O exemplo a seguir é de uma versão antiga da página da Wikipedia mencionada em outra resposta.

import java.util.*;

public class Animal 
{
   public void eat() 
   { 
      System.out.println("I eat like a generic Animal."); 
   }

   public static void main(String[] args) 
   {
      List<Animal> animals = new LinkedList<Animal>();

      animals.add(new Animal());
      animals.add(new Fish());
      animals.add(new Goldfish());
      animals.add(new OtherAnimal());

      for (Animal currentAnimal : animals) 
      {
         currentAnimal.eat();
      }
   }
}

class Fish extends Animal 
{
   @Override
   public void eat() 
   { 
      System.out.println("I eat like a fish!"); 
   }
}

class Goldfish extends Fish 
{
   @Override
   public void eat() 
   { 
      System.out.println("I eat like a goldfish!"); 
   }
}

class OtherAnimal extends Animal {}

Resultado:

Eu como como um animal genérico.
Eu como como um peixe!
Eu como como um peixe dourado!
Eu como como um animal genérico.

Exemplo com funções virtuais com interfaces

Os métodos de interface Java são todos virtuais. Eles devem ser virtuais porque dependem das classes de implementação para fornecer as implementações do método. O código a ser executado será selecionado apenas no tempo de execução.

Por exemplo:

interface Bicycle {         //the function applyBrakes() is virtual because
    void applyBrakes();     //functions in interfaces are designed to be 
}                           //overridden.

class ACMEBicycle implements Bicycle {
    public void applyBrakes(){               //Here we implement applyBrakes()
       System.out.println("Brakes applied"); //function
    }
}

Exemplo com funções virtuais com classes abstratas.

Semelhante às interfaces As classes abstratas devem conter métodos virtuais, porque contam com a implementação das classes estendidas. Por exemplo:

abstract class Dog {                   
    final void bark() {               //bark() is not virtual because it is 
        System.out.println("woof");   //final and if you tried to override it
    }                                 //you would get a compile time error.

    abstract void jump();             //jump() is a "pure" virtual function 
}                                     
class MyDog extends Dog{
    void jump(){
        System.out.println("boing");    //here jump() is being overridden
    }                                  
}
public class Runner {
    public static void main(String[] args) {
        Dog dog = new MyDog();       // Create a MyDog and assign to plain Dog variable
        dog.jump();                  // calling the virtual function.
                                     // MyDog.jump() will be executed 
                                     // although the variable is just a plain Dog.
    }
}

1
Essa deve ser a resposta mais completa. Ele fornece 2 maneiras de implementar uma função virtual, pois java não possui a palavra-chave. Obrigado.
Christopher Bales

Resposta muito melhor do que a citação da Wikipedia. Vindo de c ++ e sendo preguiçoso com meus estudos de Java, abstrato era o que eu estava procurando.
David

@ David Como esta resposta é melhor? A citação da wikipedia é completa, concisa e correta. Esta resposta, por outro lado, não menciona o elefante na sala: Por padrão, todas as funções em Java (com as exceções listadas no artigo da wikipedia) são virtuais. Nem classes abstratas nem interfaces são necessárias para funções virtuais; portanto, isso apenas adiciona ruído enganador. E então isso "requer grandes habilidades de comunicação e um profundo domínio dos princípios subjacentes" ... caramba. Essa é uma afirmação auto-falsificadora ali mesmo: ninguém que a tivesse desperdiçaria um espaço em disco valioso.
Peter - Restabelece Monica

O post da wikipedia é inferior e menos específico para esta resposta, porque se trata do conceito de funções virtuais em qualquer idioma, e não apenas em java. O exemplo dado na página da wikipedia está escrito em C, e é incompleto, na melhor das hipóteses, e é mais enganoso. Os detalhes sobre todas as funções serem virtuais e que você não precisa de classes ou interfaces abstratas para que as funções virtuais sejam ruído. Eu nunca disse que eles são necessários, você leu errado. Não estou entendendo o seu ponto final. Deseja que eu exclua esta pergunta porque não gosta?
precisa saber é o seguinte

1
Poucos anos mais tarde aqui, mas resposta fantástica
Tom O.

55

Todas as funções em Java são virtuais por padrão.

Você precisa fazer o possível para escrever funções não virtuais adicionando a palavra-chave "final".

É o oposto do padrão C ++ / C #. As funções de classe não são virtuais por padrão; você faz isso adicionando o modificador "virtual".


4
funções privadas como declaradas na resposta de Klaus também não são virtuais.
Don Laringe

9

Todos os métodos de instância não privados são virtuais por padrão em Java.

No C ++, métodos privados podem ser virtuais. Isso pode ser explorado para o idioma da interface não virtual (NVI). Em Java, você precisa proteger os métodos substituíveis pelo NVI.

Na especificação da linguagem Java, v3:

8.4.8.1 Substituição (por métodos de instância) Um método de instância m1 declarado em uma classe C substitui outro método de instância, m2, declarado na classe A, se todas as seguintes opções forem verdadeiras:

  1. C é uma subclasse de A.
  2. A assinatura de m1 é uma subsignatura (§8.4.2) da assinatura de m2.
  3. * M2 é público, protegido ou declarado com acesso padrão no mesmo pacote que C, ou * m1 substitui um método m3, m3 distinto de m1, m3 distinto de m2, de modo que m3 substitui m2.

4

Sim, você pode escrever "funções" virtuais em Java.


1

Em Java, todas as variáveis ​​e funções públicas (não privadas) são virtuais por padrão. Além disso, variáveis ​​e funções usando a palavra-chave final não são virtuais .


o que você quer dizer com "variáveis ​​virtuais"?
Neoexpert 18/11/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.