Довольно давно я писал о Overriding v / s Hiding . В этом посте я хотел бы кратко объяснить с примерами полиморфизма во время выполнения в Java. Этот пост должен был быть написан до Overriding v / s Hiding , но лучше поздно, чем никогда.
Давайте рассмотрим следующее Vehicleи Carи Truckкласс:
class Vehicle{
public void drive(){
System.out.println("Driving vehicle ...");
}
}
class Car extends Vehicle{
@Override
public void drive(){
System.out.println("Driving car...");
}
}
class Truck extends Vehicle{
@Override
public void drive(){
System.out.println("Driving truck...");
}
public void load(){
System.out.println("Loading truck...");
}
}
А Vehicleможно управлять, так же как Carи Truck. Но в дополнение к этому Truckможно загружать товары. Давайте создадим экземпляры этих классов и drive()их и попробуем также load()грузовик.
public class RunTimePolymorphismDemo {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.drive();
Vehicle carVehicle = new Car();
carVehicle.drive();
Vehicle truckVehicle = new Truck();
truckVehicle.drive();
//Compile time error
//truckVehicle.load();
Truck truck = new Truck();
truck.load();
}
}
И вывод:
Driving vehicle ... Driving car... Driving truck... Loading truck...
Если бы не задействованный полиморфизм времени исполнения, результат был бы: Driving vehicle ...для всех трех вызовов drive()метода. Вы также можете увидеть, что это truckVehicle.drive()приводит к ошибке времени компиляции. Так что же происходит в приведенном выше коде?
Любое объявление и создание объекта состоит из двух частей: тип ссылки и тип созданного объекта. Например, в Vehicle carVehicle = new Car()ссылочном типе Vehicleи созданный объект имеет тип Car. Такое присвоение возможно только в том случае, если созданный объект типа является подклассом ссылочного типа, т.е. в случаях, когда используется наследование.
Каждая ссылка на объект может использоваться для вызова методов, и методы, которые могут быть вызваны, определяются на основе ссылочного типа. И это решается во время компиляции. Но реализация, которая будет вызвана, определяется на основе типа созданного объекта. В приведенном выше примере: carVehicle.drive()компилируется, потому что drive()метод является частью Vehicleкласса и дает Driving car...в качестве выходных данных, потому что метод переопределяется Carклассом. На аналогичных строках: truckVehicle.load()выдает ошибку времени компиляции, потому что метод load()не является частью Vehicleкласса, но определяется только в Truckклассе. Но truck.load()компилируется, потому что ссылочный тип является Truckклассом, и компилятор может разрешить load()метод.
Чтобы подвести итог:
- Привязка метода происходит во время компиляции, то есть какие методы могут быть вызваны для данного ссылочного типа, определяется во время компиляции.
- Выбор реализации метода для выполнения происходит во время выполнения, т. Е. Какая реализация метода, который должен быть выполнен, т.е. версия суперкласса или одна из версий подкласса, определяется во время выполнения, и именно это приводит к полиморфизму времени выполнения.
Есть много мест, где задействован полиморфизм времени исполнения, но я не могу сказать ни одного из них: Dependency Injection, Coding to Interface .