Risposte:
In Java , tutti i metodi non statici sono per impostazione predefinita " funzioni virtuali " . Solo i metodi contrassegnati con la parola chiave final , che non possono essere sovrascritti, insieme ai metodi privati , che non sono ereditati, non sono virtuali .
Sì. In effetti, tutti i metodi di istanza in Java sono virtuali per impostazione predefinita. Solo alcuni metodi non sono virtuali:
Ecco alcuni esempi:
Funzioni virtuali "normali"
L'esempio seguente è tratto da una vecchia versione della pagina di Wikipedia citata in un'altra risposta.
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 {}
Produzione:
Mangio come un animale generico. Mangio come un pesce! Mangio come un pesce rosso! Mangio come un animale generico.
Esempio con funzioni virtuali con interfacce
I metodi di interfaccia Java sono tutti virtuali. Essi devono essere virtuale perché si basano sulle classi di attuazione di fornire delle implementazioni del metodo. Il codice da eseguire sarà selezionato solo in fase di esecuzione.
Per esempio:
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
}
}
Esempio con funzioni virtuali con classi astratte.
Simile alle interfacce Le classi astratte devono contenere metodi virtuali perché si basano sull'implementazione delle classi estese. Per esempio:
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.
}
}
Tutte le funzioni in Java sono virtuali per impostazione predefinita.
Devi fare di tutto per scrivere funzioni non virtuali aggiungendo la parola chiave "finale".
Questo è l'opposto del valore predefinito C ++ / C #. Le funzioni di classe sono non virtuali per impostazione predefinita; li rendi così aggiungendo il modificatore "virtuale".
Tutti i metodi di istanza non privati sono virtuali per impostazione predefinita in Java.
In C ++, i metodi privati possono essere virtuali. Questo può essere sfruttato per il linguaggio non-virtual-interface (NVI). In Java, è necessario rendere protetti i metodi sostituibili NVI.
Da Java Language Specification, v3:
8.4.8.1 Sostituzione (con metodi di istanza) Un metodo di istanza m1 dichiarato in una classe C ignora un altro metodo di istanza, m2, dichiarato in classe A se sono vere tutte le seguenti condizioni:
- C è una sottoclasse di A.
- La firma di m1 è una sottoscrizione (§8.4.2) della firma di m2.
- * M2 è pubblico, protetto o dichiarato con accesso predefinito nello stesso pacchetto di C, oppure * m1 ignora un metodo m3, m3 distinto da m1, m3 distinto da m2, in modo tale che m3 ignori m2.
In Java, tutte le variabili e le funzioni pubbliche (non private) sono Virtuali per impostazione predefinita. Inoltre, le variabili e le funzioni che utilizzano la parola chiave final non sono virtuali .