Что такое виртуальный метод вызова в Java?
Я видел следующий абзац в каком-то тесте по информатике, и я надеюсь, что смогу получить здесь хорошее объяснение того, что это значит, потому что я погуглил его в течение часа и ничего не могу найти...
"Когда мы говорим, что в языке Java есть вызов виртуального метода, мы имеем в виду, что в Java-приложениях исполняемый метод определяется типом объекта во время выполнения"
Что это значит? кто-нибудь может объяснить это лучше?
4 ответа
Автор этих строк использовал терминологию C++ virtual
,
Лучшая терминология - динамическое связывание / динамическая отправка.
Это означает, что динамический тип объекта "выбирает", какой метод будет вызываться, а не статический тип.
Например: [псевдокод]:
class A {
public void foo() { }
}
class B extends A {
public void foo() { }
}
при вызове:
A obj = new B();
obj.foo();
B.foo()
будет вызван, а НЕ A.foo()
, поскольку динамический тип obj
является B
,
мы имеем в виду, что в Java-приложениях исполняемый метод определяется типом объекта во время выполнения
interface Animal{
public void eat();
}
class Person implements Animal{
public void eat(){ System.out.println("Eating Food");}
}
class Eagle implements Animal{
public void eat(){ System.out.println("Eating Snake");}
}
в основном
Animal animal = new Person();
animal.eat(); //it will print eating food
animal = new Eagle();
animal.eat(); //it will print eating snake
Предположим, у вас есть класс Fruit с двумя подклассами Orange и Banana. И предположим, что фрукт имеет String getColor()
метод.
Оранжевый может перекрыть getColor()
способ вернуть "апельсин". То же самое для банана, который может вернуть "желтый".
Когда какой-то метод использует объект типа Fruit и вызывает getColor()
метод, метод, который будет вызван Banana.getColor()
если тип Фрукта на самом деле Банан.
private void printColor(Fruit f) {
System.out.println(f.getColor());
}
...
Fruit fruit1 = new Banana();
Fruit fruit2 = new Orange();
printColor(fruit1); // prints yellow
printColor(fruit2); // prints orange
Employee.java
public class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
}
VirtualMethod.java
class Salary extends Employee
{
private double salary; //Annual salary
public Salary(String name, String address, int number, double
salary)
{
super(name, address, number);
this.salary=salary;
}
public void mailCheck()
{
System.out.println("Within mailCheck of Salary class ");
System.out.println("Mailing check to "
+ " with salary " + salary);
}
}
public class VirtualMethod
{
public static void main(String [] args)
{
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
System.out.println("Call mailCheck using Salary reference --");
s.mailCheck();
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
Выход
Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class
Mailing check to with salary 3600.0
Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to with salary 2400.0
объяснение
здесь мы создаем два экземпляра Salary
объекты. Один с помощью Salary
ссылка s
, а другой с помощью Employee
ссылка e
,
Во время вызова s.mailCheck()
компилятор видит mailCheck()
в Salary
класс во время компиляции, и JVM вызывает mailCheck()
в Salary
класс во время выполнения.
Вызов mailCheck()
на e
совсем другой, потому что e
является Employee
ссылка. Когда компилятор видит e.mailCheck()
компилятор видит mailCheck()
метод в Employee
учебный класс.
Здесь во время компиляции использовался компилятор mailCheck()
в Employee
чтобы подтвердить это утверждение. Однако во время выполнения JVM вызывает mailCheck()
в Salary
учебный класс.