Как виртуальные функции работают на С# и Java?
Использует ли он такую же концепцию vtable и vpointer, что и для С++, или это нечто совершенно другое?
Как виртуальные функции работают на С# и Java?
Использует ли он такую же концепцию vtable и vpointer, что и для С++, или это нечто совершенно другое?
Кодирующие интервьюеры любят этот вопрос. Да. Хотя 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.
}
}
В 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
В виртуальной виртуальной реальности Java совершенно иная. В Java виртуальная функция означает функцию, которая может быть переопределена в своих подклассах. Таким образом, все нестатические методы Java являются виртуальной функцией. Только конечная и частная функция не наследуются, поэтому они не являются виртуальной функцией.
Итак, мы можем сказать, что все нестатические функции, которые не являются окончательными и частными, являются виртуальной функцией в Java.
Все языки, поддерживающие полиморфизм, используют vtables для разрешения вызовов методов на правильную функцию. Так и Java и .NET.
Они оба скомпилированы для некоторого промежуточного langauge (IL для .NET и байтового кода для java), но vtable не отображается на этом промежуточном языке. Он поддерживается базовым движком (CLR для .NET).
Я уверен, что Java не использует vtables, так как он способен поддерживать двоичную совместимость.
To Clarify: vtable создается, когда скомпилирован производный/подкласс. Если макет базового класса/суперкласса изменяется, необходимо перекомпилировать таблицу vtable для d/s. В Java это не так. Вы можете изменить b/s, не перекомпилируя d/s.
Хммм. Возможно, что vtable построена во время выполнения. когда класс загружен. В этом случае Java и С++ будут одинаковыми, но разными.
Чистые виртуальные функции находятся на С++. С# использует интерфейсы для выполнения той же цели, поэтому я предлагаю вам пройти этот маршрут.