Довольно давно я писал о 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 .