Ответы:
В Java все нестатические методы по умолчанию являются « виртуальными функциями». Только методы, отмеченные ключевым словом final , которые нельзя переопределить, наряду с закрытыми методами , которые не наследуются, не являются виртуальными .
Да. Фактически все методы экземпляра в Java являются виртуальными по умолчанию. Только определенные методы не являются виртуальными:
Вот некоторые примеры:
«Нормальные» виртуальные функции
Следующий пример взят из старой версии страницы википедии, упомянутой в другом ответе.
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 {}
Вывод:
Я ем как универсальное животное. Я ем как рыба! Я ем как золотая рыбка! Я ем как универсальное животное.
Пример с виртуальными функциями с интерфейсами
Все методы интерфейса Java являются виртуальными. Они должны быть виртуальными, потому что они полагаются на реализующие классы для обеспечения реализации методов. Код для выполнения будет выбран только во время выполнения.
Например:
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
}
}
Пример с виртуальными функциями с абстрактными классами.
Подобно интерфейсам Абстрактные классы должны содержать виртуальные методы, потому что они полагаются на реализацию расширяющихся классов. Например:
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.
}
}
Все функции в Java являются виртуальными по умолчанию.
Вы должны изо всех сил писать не виртуальные функции, добавив ключевое слово «final».
Это противоположность C ++ / C # по умолчанию. Функции класса не являются виртуальными по умолчанию; вы делаете их так, добавляя «виртуальный» модификатор.
Все не частные методы экземпляров по умолчанию являются виртуальными в Java.
В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы не-виртуального интерфейса (NVI). В Java вам нужно сделать защищенные переопределяемые методы NVI.
Из спецификации языка Java, версия 3:
8.4.8.1 Переопределение (с помощью методов экземпляра) Метод экземпляра m1, объявленный в классе C, переопределяет другой метод экземпляра, m2, объявленный в классе A, если все следующее верно:
- C является подклассом A.
- Подпись m1 является подписью (§8.4.2) подписи m2.
- Либо * m2 является общедоступным, защищенным или объявленным с доступом по умолчанию в том же пакете, что и C, либо * m1 переопределяет метод m3, m3 отличается от m1, m3 отличается от m2, так что m3 переопределяет m2.
В Java все общедоступные (не частные) переменные и функции являются виртуальными по умолчанию. Более того, переменные и функции, использующие ключевое слово final , не являются виртуальными .