Pouvez-vous écrire des fonctions / méthodes virtuelles en Java?

166

Est-il possible d'écrire des méthodes virtuelles en Java, comme on le ferait en C ++?

Ou existe-t-il une approche Java appropriée que vous pouvez implémenter et qui produit un comportement similaire? Puis-je avoir quelques exemples?

Yonatan
la source

Réponses:

306

De wikipedia

En Java , toutes les méthodes non statiques sont par défaut des « fonctions virtuelles » . Seules les méthodes marquées du mot - clé final , qui ne peuvent pas être remplacées, ainsi que les méthodes privées , qui ne sont pas héritées, ne sont pas virtuelles .

Klaus Byskov Pedersen
la source
3
Voici une des réponses de Jon Skeet .
Quazi Irfan
Je me suis demandé si c'était vraiment vrai, car pour ce que j'ai lu, en Java, la répartition dynamique de la méthode ne se produit que pour l'objet sur lequel la méthode est appelée - comme expliqué ici , l'exemple expliquant les fonctions virtuelles pour C ++ ici n'est pas valide pour java.
Brocoli
@QuaziIrfan C'est la différence entre Java et C #.
Sreekanth Karumanaghat
101

Pouvez-vous écrire des fonctions virtuelles en Java?

Oui. En fait, toutes les méthodes d'instance de Java sont virtuelles par défaut. Seules certaines méthodes ne sont pas virtuelles:

  • Méthodes de classe (car généralement, chaque instance contient des informations comme un pointeur vers une table virtuelle sur ses méthodes spécifiques, mais aucune instance n'est disponible ici).
  • Méthodes d'instance privée (car aucune autre classe ne peut accéder à la méthode, l'instance appelante a toujours le type de la classe de définition elle-même et est donc connue sans ambiguïté au moment de la compilation).

Voici quelques exemples:

Fonctions virtuelles "normales"

L'exemple suivant provient d'une ancienne version de la page wikipedia mentionnée dans une autre réponse.

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 {}

Production:

Je mange comme un animal générique.
Je mange comme un poisson!
Je mange comme un poisson rouge!
Je mange comme un animal générique.

Exemple avec fonctions virtuelles avec interfaces

Les méthodes d'interface Java sont toutes virtuelles. Ils doivent être virtuels car ils s'appuient sur les classes d'implémentation pour fournir les implémentations de méthode. Le code à exécuter ne sera sélectionné qu'au moment de l'exécution.

Par exemple:

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
    }
}

Exemple avec des fonctions virtuelles avec des classes abstraites.

Similaire aux interfaces Les classes abstraites doivent contenir des méthodes virtuelles car elles reposent sur l'implémentation des classes étendues. Par exemple:

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.
    }
}
Eric Leschinski
la source
1
Cela doit être la réponse la plus complète. Il fournit 2 façons d'implémenter une fonction virtuelle puisque java n'a pas le mot-clé. Je vous remercie.
Christopher Bales
Bien meilleure réponse que la citation Wikipedia. Venant de C ++ et paresseux avec mes études Java, le résumé était ce que je recherchais.
David
@David En quoi cette réponse est-elle meilleure? La citation de wikipedia est complète, concise et correcte. Cette réponse, en revanche, ne mentionne pas l'éléphant dans la pièce: par défaut, toutes les fonctions de Java (à l'exception des exceptions répertoriées dans l'article de wikipedia) sont virtuelles. Ni les classes abstraites ni les interfaces ne sont nécessaires pour les fonctions virtuelles, donc cela ne fait qu'ajouter du bruit trompeur. Et puis cela "nécessite de grandes compétences en communication et une maîtrise profonde des principes sous-jacents" ... jeez. C'est une affirmation qui se falsifie d'elle-même: personne qui en possédait ne gaspillerait un espace disque précieux avec.
Peter - Réintègre Monica
Le post de wikipedia est inférieur et moins spécifique à cette réponse car il concerne le concept de fonctions virtuelles dans n'importe quel langage, plutôt que juste java. L'exemple donné dans la page wikipedia est écrit en C, et c'est au mieux incomplet, et c'est plus trompeur. Le détail sur toutes les fonctions étant virtuelles et le fait que vous n'avez pas besoin de classes ou d'interfaces abstraites pour avoir des fonctions virtuelles étant du bruit. Je n'ai jamais dit qu'ils étaient nécessaires, vous avez mal interprété cela. Je ne comprends pas votre dernier point, voulez-vous que je supprime cette question parce que vous ne l'aimez pas?
Eric Leschinski
1
Quelques années de retard ici mais réponse fantastique
Tom O.janvier
55

Toutes les fonctions de Java sont virtuelles par défaut.

Vous devez faire tout votre possible pour écrire des fonctions non virtuelles en ajoutant le mot-clé «final».

C'est l'opposé de la valeur par défaut C ++ / C #. Les fonctions de classe ne sont pas virtuelles par défaut; vous les rendez ainsi en ajoutant le modificateur "virtuel".

duffymo
la source
4
les fonctions privées comme indiqué dans la réponse de Klaus sont également non virtuelles.
Don Larynx
9

Toutes les méthodes d'instance non privées sont virtuelles par défaut en Java.

En C ++, les méthodes privées peuvent être virtuelles. Cela pourrait être exploité pour l'idiome non-virtual-interface (NVI). En Java, vous devez protéger les méthodes remplaçables NVI.

À partir de la spécification du langage Java, v3:

8.4.8.1 Remplacement (par les méthodes d'instance) Une méthode d'instance m1 déclarée dans une classe C remplace une autre méthode d'instance, m2, déclarée dans la classe A ssi toutes les conditions suivantes sont vraies:

  1. C est une sous-classe de A.
  2. La signature de m1 est une sous-signature (§8.4.2) de la signature de m2.
  3. Soit * m2 est public, protégé ou déclaré avec accès par défaut dans le même package que C, soit * m1 remplace une méthode m3, m3 distincte de m1, m3 distincte de m2, de sorte que m3 remplace m2.
Andy Thomas
la source
4

Oui, vous pouvez écrire des «fonctions» virtuelles en Java.

RepDetec
la source
1

En Java, toutes les variables et fonctions publiques (non privées) sont virtuelles par défaut. De plus, les variables et fonctions utilisant le mot-clé final ne sont pas virtuelles .

Parvej Ahmed
la source
qu'entendez-vous par «variables virtuelles»?
neoexpert