Можете ли вы написать виртуальные функции / методы в Java? - PullRequest
144 голосов
/ 28 декабря 2010

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

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

Ответы [ 6 ]

272 голосов
/ 28 декабря 2010

из википедии

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

89 голосов
/ 18 июля 2013

Можете ли вы писать виртуальные функции на 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.
    }
}
54 голосов
/ 28 декабря 2010

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

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

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

9 голосов
/ 28 декабря 2010

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

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

Из спецификации языка Java, v3:

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

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

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

0 голосов
/ 25 сентября 2016

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...