Как работают виртуальные функции в C # и Java?

17

Как виртуальные функции работают на С# и Java?

Использует ли он такую ​​же концепцию vtable и vpointer, что и для С++, или это нечто совершенно другое?

  • 0
    Да, они разделяют ту же концепцию. Вот ссылка на описание вызовов методов в .NET Статья о таблицах виртуальных методов в Википедии
Теги:
virtual
vtable

6 ответов

17

Как виртуальные функции работают в Java?

Кодирующие интервьюеры любят этот вопрос. Да. Хотя Java не имеет виртуального ключевого слова, Java имеет виртуальные функции, и вы можете их записать.

В объектно-ориентированном программировании виртуальная функция или виртуальный метод - это функция или метод, поведение которых можно переопределить внутри наследующего класса посредством функция с той же сигнатурой. Это понятие является очень важной частью части полиморфизма объектно-ориентированного программирования (ООП).

Задавая вопрос архитектуры об определенном языке, как это требует больших навыков общения и глубокого освоения лежащих в основе принципов Java-компилятора, в частности интерфейсов, абстрактных классов и того, как работает наследование.

Направьте интервьюера на конкретный пример виртуальной функции.

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

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 implementing applyBrakes()
       System.out.println("Brakes applied"); //function, proving it is virtual.
    }
}

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

Java Абстрактные классы содержат неявно "виртуальные" методы, реализуемые классами, расширяющими его. Например:

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 virtual function because it
}                                     //is part of an abstract class and isn't
                                      //final.  
class MyDog extends Dog{
    void jump(){
        System.out.println("boing");    //here jump() is being overridden, a 
    }                                   //demonstration that it is virtual.
}
public class Runner {
    public static void main(String[] args) {
        MyDog myDog = new MyDog();       //instantiating myDog
        myDog.jump();                    //calling the overridden function jump()
    }
}

Вы можете заставить функцию НЕ быть виртуальной в родовом классе, сделав ее final

Например:

class myJavaFoobarClass {

    final boolean giveMeTrueFunction()   //this Java function is NOT virtual
    {                                    //because final keyword prevents this
        return true;                     //function from being modified in a
    }                                    //subclass.

    boolean isItRainingFunction()   //this Java function IS virtual because
    {                               //without the final keyword, the function
        return false;               //can be overridden in a subclass.
    }
}
10

В Java нет виртуального ключевого слова.

Он просто решает самую производную версию любого метода, который вы вызываете...

class A{
void sayhi(){ System.out.println("A");}
}
class B extends A{
void sayhi(){ System.out.println("B");}
}

A a = new B();
a.sayhi();

Будет напечатан "B".

Вы можете создавать "чистые виртуальные" методы, объявляя класс Abstract и оставляя чистые виртуальные методы объявленными, но не реализованными. Или с помощью интерфейса/инструментов вместо класса /extends. Интерфейс - это в основном класс, где все методы являются чисто виртуальными. У этого есть дополнительный бонус, что класс может реализовать несколько интерфейсов, поскольку в отличие от С++ класс Java может наследовать только один класс напрямую.

EDIT:


В ответ на ваш комментарий, Naveen:

Если вы сказали A a = new A(); a.sayhi(); он будет печатать "A".

Терминология java является динамической. Вы можете считать это виртуальным, но это может смутить некоторых разработчиков Java. те, кто не знает С++, по крайней мере. В Java нет явных указателей, поэтому нам не нужно беспокоиться о виртуальном/не виртуальном. Нет VTables, вы просто возвращаетесь к классу и его предкам, пока не найдете реализацию метода, который вы хотите. Там только одно наследование, поэтому вам не нужно беспокоиться о порядке конструкторов (он всегда снизу вверх).

В С++ вы получаете другое поведение, если у вас есть виртуальные методы и что-то вроде

a->sayhi();

где a было A *, указывающим на экземпляр B вместо

a.sayhi();

где a - объект типа A, содержащий объект типа B

  • 0
    Я знаю, что в Java нет виртуального ключевого слова, но не все ли виртуальное там по умолчанию? Кстати, в приведенном выше примере, что происходит, если A a = new A (); a.sayhi (); В этом случае, как мы можем определить во время выполнения, какую функцию вызывать?
  • 0
    Почему вы ожидаете что-то еще, когда вызывается A.sayhi ()? Вы создали объект типа A, поэтому, конечно, выполняется A.sayhi () и печатается «A».
Показать ещё 1 комментарий
4

В виртуальной виртуальной реальности Java совершенно иная. В Java виртуальная функция означает функцию, которая может быть переопределена в своих подклассах. Таким образом, все нестатические методы Java являются виртуальной функцией. Только конечная и частная функция не наследуются, поэтому они не являются виртуальной функцией.

Итак, мы можем сказать, что все нестатические функции, которые не являются окончательными и частными, являются виртуальной функцией в Java.

2

Все языки, поддерживающие полиморфизм, используют vtables для разрешения вызовов методов на правильную функцию. Так и Java и .NET.

Они оба скомпилированы для некоторого промежуточного langauge (IL для .NET и байтового кода для java), но vtable не отображается на этом промежуточном языке. Он поддерживается базовым движком (CLR для .NET).

0

Я уверен, что Java не использует vtables, так как он способен поддерживать двоичную совместимость.

To Clarify: vtable создается, когда скомпилирован производный/подкласс. Если макет базового класса/суперкласса изменяется, необходимо перекомпилировать таблицу vtable для d/s. В Java это не так. Вы можете изменить b/s, не перекомпилируя d/s.

Хммм. Возможно, что vtable построена во время выполнения. когда класс загружен. В этом случае Java и С++ будут одинаковыми, но разными.

  • 0
    Не знаете, как виртуальная таблица (т. Е. Таблица указателей на функции), используемая во время выполнения, препятствует двоичной совместимости?
  • 0
    Я думал, что так как расположение базового объекта может измениться, поиск должен пройти дополнительный уровень косвенности.
Показать ещё 1 комментарий
-2

Чистые виртуальные функции находятся на С++. С# использует интерфейсы для выполнения той же цели, поэтому я предлагаю вам пройти этот маршрут.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню