Можете ли вы написать виртуальные функции / методы в Java?

166

Можно ли писать виртуальные методы в Java, как в C ++?

Или есть ли подходящий подход Java, который вы можете реализовать, который производит подобное поведение? Могу я привести несколько примеров?

Йонатан
источник

Ответы:

306

Из википедии

В Java все нестатические методы по умолчанию являются « виртуальными функциями». Только методы, отмеченные ключевым словом final , которые нельзя переопределить, наряду с закрытыми методами , которые не наследуются, не являются виртуальными .

Клаус Бысков Педерсен
источник
3
Вот один из ответов Джона Скита .
Quazi Irfan
Я wonded , если это действительно так, потому что я читал, в Java, динамический способ доставки происходит только для объекта , метод вызывается - как описано здесь , так что пример объяснения виртуальных функций для C ++ здесь не действует для Java.
Брокколи
@QuaziIrfan Это разница между Java и C #.
Sreekanth Karumanaghat
101

Можете ли вы написать виртуальные функции на 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 {}

Вывод:

Я ем как универсальное животное.
Я ем как рыба!
Я ем как золотая рыбка!
Я ем как универсальное животное.

Пример с виртуальными функциями с интерфейсами

Все методы интерфейса 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.
    }
}
Эрик Лещинский
источник
1
Это должен быть самый полный ответ. Он предоставляет 2 способа реализации виртуальной функции, поскольку в Java нет ключевого слова. Спасибо.
Кристофер Бейлс
Гораздо лучший ответ, чем цитата из Википедии. Исходя из c ++ и ленивый в изучении Java, я искал резюме.
Дэвид
@ Дэвид Как этот ответ лучше? Цитата из Википедии полная, лаконичная и правильная. В этом ответе, напротив, не упоминается слон в комнате: по умолчанию все функции в Java (с исключениями, перечисленными в статье в википедии) являются виртуальными. Для виртуальных функций не нужны ни абстрактные классы, ни интерфейсы, так что это только добавляет ложного шума. И тогда это «требует отличных коммуникативных навыков и глубокого овладения основополагающими принципами» ... господи. Это самоутверждающее утверждение прямо здесь: никто, кто имел это, не потратил бы на это ценное дисковое пространство.
Питер - Восстановить Монику
Пост Википедии ниже и менее специфичен для этого ответа, потому что он касается концепции виртуальных функций на любом языке, а не просто Java. Пример, приведенный на странице википедии, написан на C, в лучшем случае он неполон и более обманчив. Подробности о том, что все функции являются виртуальными, и что вам не нужны абстрактные классы или интерфейсы, чтобы виртуальные функции были шумом. Я никогда не говорил, что они необходимы, вы неправильно это поняли. Я не понимаю вашу последнюю мысль, вы хотите, чтобы я удалил этот вопрос, потому что он вам не нравится?
Эрик Лещинский
1
Несколько лет спустя, но фантастический ответ
Том О.
55

Все функции в Java являются виртуальными по умолчанию.

Вы должны изо всех сил писать не виртуальные функции, добавив ключевое слово «final».

Это противоположность C ++ / C # по умолчанию. Функции класса не являются виртуальными по умолчанию; вы делаете их так, добавляя «виртуальный» модификатор.

duffymo
источник
4
частные функции, как указано в ответе Клауса, также не являются виртуальными.
Дон Ларинкс
9

Все не частные методы экземпляров по умолчанию являются виртуальными в Java.

В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы не-виртуального интерфейса (NVI). В Java вам нужно сделать защищенные переопределяемые методы NVI.

Из спецификации языка Java, версия 3:

8.4.8.1 Переопределение (с помощью методов экземпляра) Метод экземпляра m1, объявленный в классе C, переопределяет другой метод экземпляра, m2, объявленный в классе A, если все следующее верно:

  1. C является подклассом A.
  2. Подпись m1 является подписью (§8.4.2) подписи m2.
  3. Либо * m2 является общедоступным, защищенным или объявленным с доступом по умолчанию в том же пакете, что и C, либо * m1 переопределяет метод m3, m3 отличается от m1, m3 отличается от m2, так что m3 переопределяет m2.
Энди Томас
источник
4

Да, вы можете писать виртуальные «функции» в Java.

RepDetec
источник
1

В Java все общедоступные (не частные) переменные и функции являются виртуальными по умолчанию. Более того, переменные и функции, использующие ключевое слово final , не являются виртуальными .

Парвей Ахмед
источник
что вы подразумеваете под "виртуальными переменными"?
neoexpert