Что такое вызов виртуального метода в 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
is 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()
метод для возврата "orange". То же самое для банана, который может вернуть "желтый".
когда какой-то метод использует объект типа 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
сотрудник.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()
on e
- это совсем другое, потому что e
это Employee
ссылка. Когда компилятор видит e.mailCheck()
компилятор видит mailCheck()
метод Employee
класса.
здесь, во время компиляции, компилятор использовать mailCheck()
на Employee
для проверки этого утверждения. Однако во время выполнения JVM вызывает mailCheck()
на Salary
класса.