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