Можете ли вы писать виртуальные функции на Java?
Да. Фактически, все методы экземпляра в 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 {}
Выход:
I eat like a generic Animal.
I eat like a fish!
I eat like a goldfish!
I eat like a generic 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.
}
}