Можете ли вы написать виртуальные функции / методы на Java?
можно писать виртуальный методы в Java, как это было бы в C++?
или, есть ли правильный подход Java, который вы можете реализовать, который производит подобное поведение? Могу я привести несколько примеров?
6 ответов
с Википедия
на Java, все нестатические методы по по умолчанию "виртуальные функции." только методы, отмеченные ключевое слово final, который нельзя отменить, вместе с частные методы, которые не в наследство, являются non-virtual.
можете ли вы писать виртуальные функции на Java?
да. Фактически, все методы экземпляра в Java являются виртуальными по умолчанию. Только некоторые методы не являются виртуальными:
- методы класса (потому что обычно каждый экземпляр содержит информацию, такую как указатель на vtable о его конкретных методах, но экземпляр здесь недоступен).
- методы частного экземпляра (поскольку ни один другой класс не может получить доступ к методу, вызывающий экземпляр всегда имеет тип определение самого класса и поэтому однозначно известно во время компиляции).
вот несколько примеров:
"нормальные" виртуальные функции
следующий пример из старая версия страницы Википедии, упомянутой в другом ответе.
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 методы интерфейса все виртуальный. Они!--33-->должны быть виртуальными, потому что они полагаются на классы реализации для предоставления реализаций метода. Код для выполнения будет выбран только во время выполнения.
например:
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# по умолчанию. По умолчанию функции класса не являются виртуальными; вы делаете их так, добавляя модификатор "virtual".
все non-private методы экземпляра являются виртуальными по умолчанию в Java.
В C++, частные методы могут быть виртуальными. Это можно использовать для идиомы non-virtual-interface (NVI). В Java вам нужно будет защитить переопределяемые методы NVI.
из спецификации языка Java, v3:
8.4.8.1 переопределение (методами экземпляра) метода экземпляра m1 объявленные в классе C может другой метод экземпляра, м2, объявленный в классе A iff все следующие верны:
- C является подклассом А.
- подпись M1 подподписью (§8.4.2) подписи м2.
- либо * m2 является общедоступным, защищенным или объявленным с доступом по умолчанию в пакет C или * m1 переопределяет метод m3, M3, отличный от M1, m3, отличный от m2, таким образом, что m3 переопределяет m2.
в Java все открытые (не частные) переменные и функции являются виртуальный по умолчанию. Кроме того, переменные и функции с помощью ключевого слова финал не виртуальный.