Википедия определяет virtual methods как:Методы в объектно-ориентированных парадигмах могут быть переопределены методами с одинаковой сигнатурой в наследующих классах. Переменные однако не могут. Зачем?
В объектно-ориентированном программировании, виртуальная функция или виртуальный метод является функция или метода, поведение которого может быть переопределена в пределах наследуемого класса с помощью функции с той же подписью [предоставить полиморфное поведение].
Согласно определению, каждый не-статический метод в Java по умолчанию виртуальной кроме конечных и частных методов. Метод, который не может быть унаследован для полиморфного поведения, является не виртуальным методом.
Статические методы в Java никогда нельзя переопределить; следовательно, бессмысленно объявлять статический метод как final в Java, потому что сами статические методы ведут себя точно так же, как и конечные методы. Они могут просто быть скрытыми в подклассах методами с той же подписью. Очевидно, это связано с тем, что статические методы никогда не могут иметь полиморфного поведения: переопределенный метод должен обеспечивать полиморфизм, что не соответствует статическим методам.
Из предыдущего абзаца можно сделать важный вывод. Все методы в C++ по умолчанию статичны, потому что никакие методы в C++ не могут вести себя полиморфно до тех пор, пока они не будут явно объявлены виртуальными в суперклассе. Напротив, все методы в Java, за исключением конечных, статических и частных методов, по умолчанию являются виртуальными, поскольку по умолчанию они имеют полиморфное поведение (нет необходимости явно объявлять методы как виртуальные в Java и, следовательно, у Java нет ключевого слова типа "виртуальный").
Теперь давайте продемонстрируем, что переменные экземпляра (статические тоже) не могут вести себя полиморфно из следующего простого примера в Java.
class Super
{
public int a=5;
public int show()
{
System.out.print("Super method called a = ");
return a;
}
}
final class Child extends Super
{
public int a=6;
@Override
public int show()
{
System.out.print("Child method called a = ");
return a;
}
}
final public class Main
{
public static void main(String...args)
{
Super s = new Child();
Child c = new Child();
System.out.println("s.a = "+s.a);
System.out.println("c.a = "+c.a);
System.out.println(s.show());
System.out.println(c.show());
}
}
Выход производства вышеуказанного фрагмента кода состоит в следующем.
s.a = 5 c.a = 6 Child method called a = 6 Child method called a = 6
В этом примере, как называет s.show()
и c.show()
сделаны методом show()
через переменные типа Super
и типа Child
, соответственно, вызвать метод show()
в Child
классе. Это означает, что метод show()
в классе Child
переопределяет метод show()
в классе Super
, поскольку оба они имеют идентичную подпись.
Это, однако, не может применяться к переменной экземпляра a
, объявленной в обоих классах.В этом случае s.a
будет относиться к a
в Super
классе и отображения 5
и c.a
будет ссылаться на a
в Child
классе и отображения 6
означает, что a
в Child
класса просто скрывает (и не отменяет, как это случилось с нестатическая методы) a
в классе Super
.
После этого продолжительного обсуждения есть только один вопрос. Почему переменные экземпляра (и остальные тоже) не переопределены? Каковы были особые причины для реализации такого механизма? Были бы какие-то преимущества или недостатки, если бы они были переопределены?
Не виртуальные методы C++ не являются статическими. это методы экземпляров, которые нельзя переопределить. Они похожи на конечные методы в Java: методы экземпляров, которые нельзя переопределить. –
'В соответствии с вышеприведенным абзацем можно сделать важный вывод. Все методы в C++ (также в C) по умолчанию статичны, потому что никакие методы в C++ не могут вести себя полиморфно до тех пор, пока они не будут явно объявлены виртуальными в базе': статический метод не может получить доступ к объекту [no 'this' для этих методов ], в то время как не виртуальная функция [по умолчанию] в C++ может – amit
. Я считаю, что слово «переопределенное» не относится к переменным. Вы переопределяете поведение, но не состоите. Переменные могут быть доступны из подкласса, поэтому нет необходимости «переопределять» (вы можете изменить его значение и иметь одно и то же имя). Также есть что-то, называемое затенением, поэтому, если вы переопределите другую переменную с тем же именем, это другая переменная во время выполнения. –