В этой статье давайте обсудим основные и сложные концепции, лежащие в основе термина полиморфизм. Мы также обсудим некоторые хитрые способы кодирования с использованием переопределения и перегрузки методов. Это поможет взломать интервью.

Основная концепция

Основная концепция полиморфизма - это одно и то же имя, но разные функции. В java можно создавать разные функции с одним и тем же именем, все эти функции подпадают под полиморфизм.

Есть два типа полиморфизмов.

Полиморфизм времени компиляции (перегрузка метода): здесь имя метода то же, но сигнатура другая. Перегрузка метода разрешается во время компиляции, поэтому она называется полиморфизмом времени компиляции.

Полиморфизм времени выполнения (переопределение метода): здесь имя метода и подпись совпадают. Методы появляются в базовом и родительском классах. Тип возвращаемого значения методов должен быть одинаковым или совпадать. Эти методы разрешаются во время выполнения, поэтому это называется полиморфизмом времени выполнения.

Полиморфизм с примерами

Вышеупомянутое объясняет основную концепцию полиморфизма. Концепция полиморфизма проста, но доходит до практического кодирования, она способна реализовать полиморфизм простым и сложным способом. Давайте углубимся в полиморфизм, обсудив несколько примеров.

Здесь мы обсуждаем 5 различных примеров полиморфизма. Пройдя через эти примеры, давайте рассмотрим некоторые простые и сложные концепции поведения полиморфизма.

1 Первый пример - это очень простой пример, объясняющий основы полиморфизма времени выполнения и времени компиляции в кодировании.

Здесь ниже упоминаются два класса Printer и AdvancedPrinter. AdvancedPrinter the class, созданный расширением Printer class.

Printer содержит функцию с именем print(PrintData content) и класс AdvancedPrinter , созданный расширением Printer class и переопределяющий метод print(PrintData content). Это означает, что имя, параметры и возвращаемые значения функции одинаковы как для дочернего, так и для суперкласса, поэтому это называется Переопределение метода.

В AdvancedPrinter class есть две функции с одинаковым именем print. Но параметры у обеих функций разные, и это называется Перегрузка метода.

Теперь давайте посмотрим, как выполняются эти функции. Ниже показан main method.

Выше, в строке номер 3 триггеры print method на основе переменной printer implementation. Выше вы можете увидеть переменную printer create an instance of AdvancedPrinter() the class. Итак, здесь метод printer.print вызывает print method AdvancedPrinter class, и решение принимается во время создания экземпляра printer variable, что означает во время выполнения. Это пример полиморфизма времени выполнения.

Затем вы можете увидеть в строке номер 6, что система вызывает AdvancedPrinter.print(PrintData content, PrintData header, PrintData footer). Здесь метод разрешается непосредственно во время компиляции. Это пример полиморфизма времени компиляции.

2 В приведенном выше примере мы увидели основы полиморфизма времени выполнения и полиморфизма времени компиляции. Далее перейдем к более сложному примеру.

В приведенном ниже примере вы можете увидеть, что метод Printer.print переопределяется методом AdvancedPrinter.print. Здесь модификатор доступа к методам, тип возвращаемого значения и выдача исключений различны. Возможно ли это в Яве?

В приведенном выше примере вы можете увидеть метод печати расширенного класса (AdvancedPrinter.print) , тип возвращаемого значения и исключение, выброс которых является классами более высокого порядка. Кроме того, модификатор доступа является модификатором высшего порядка.

Метод Printer.print выдает PrintException, а метод AdvancedPrinter.print выдает PrintExceptions расширенный класс AdvancedPrinterException.

Метод Printer.print возвращает PrintOutput, но метод AdvancedPrinter.print возвращает расширенный класс PrintOutputs, AdvancedPrinterOutput.

Модификатор доступа к методам Printer.print защищен, но модификатор доступа к методам AdvancedPrinter.print является модификатором более высокого порядка, общедоступным.

В целом мы можем сказать, что В модификаторе доступа переопределенных методов тип возвращаемого значения и выбрасываемое исключение могут иметь значение более высокого порядка. Java допускает это.

Но помните, что Java не допускает возвращаемых типов, исключений и модификаторов доступа более низкого порядка для переопределенного метода. В этом случае Java выдает ошибку компиляции.

Из приведенного выше примера мы обнаружили, что можем использовать модификатор доступа высшего порядка, возвращаемый тип, исключение в переопределенном методе. Далее давайте посмотрим, как полиморфизм работает на примитиве и оболочке в случае перегрузки метода.

Ниже показан пример перегрузки. Здесь вы можете увидеть два метода вычисления: один принимает примитивный тип данных double, а другой принимает тип данных двойной оболочки. Я выполняю метод вычисления, минуя число «10» в качестве параметра. Какой метод будет выполнен?

Это сбивающий с толку вопрос. Для большинства экзаменов OCJP это чертовски верный вопрос.

Ниже следует вывод для приведенного выше фрагмента кода.

Invoking primitive calculate method ....

Это означает, что выполняется метод calculate(double number). Если в классе есть два перегруженных метода, один из которых использует примитивный тип данных в качестве параметра, а другой - тип данных оболочки, то приоритет отдается методу с примитивным типом данных.

Подожди подожди…. Не заканчивайте предложением выше. В приведенном выше примере я просто передаю число «10» в качестве аргумента. Но предположим, что If создаю переменную с типом данных Double, и я передаю эту переменную функции вычисления. Что-нибудь изменится в выводе?

Вышеупомянутое сомнение устраняется приведенным ниже примером. В приведенном ниже примере вы можете увидеть, что в основном методе создается переменная для разных типов данных примитива и оболочки и передаются эти переменные в функцию вычисления.

Далее следует вывод приведенного выше фрагмента кода.

====== Calling primitive datatypes ======
Invoking primitive method calculate(int number) ...
Invoking primitive method calculate(long number) ...
Invoking primitive method calculate(double number) ...
Invoking primitive method calculate(float number) ...
====== Calling wrapper datatypes ======
Invoking wrapper method calculate(Integer number) ...
Invoking wrapper method calculate(Long number) ...
Invoking wrapper method calculate(Double number) ...
Invoking wrapper method calculate(Float number) ...
====== Calling calculate function with number ======
Invoking primitive method calculate(int number) ...
Invoking primitive method calculate(float number) ...

Из вышеприведенного вывода вы можете видеть, что: Если Java может идентифицировать указанный тип данных передаваемой переменной, то она вызовет соответствующую перегруженную функцию. Если java не может определить правильный тип данных передаваемой переменной, метод будет выбран на основе приоритета типа данных.

Далее следует приоритет разных типов данных.

byte ›short› int ›long› float ›double› Byte ›Short› Integer ›Long› Float ›Double

4 Наконец, давайте посмотрим, как переопределение метода работает со статическим методом. Во-первых, вы должны помнить, что нет никакой связи между статической инициализацией и инициализацией объекта.

Если в классе есть статический метод или статическая переменная. Затем вы можете напрямую вызвать этот статический метод / переменную без инициализации этого объекта класса. Надеюсь, ты понял.

Далее давайте рассмотрим это на примере.

Ниже вы можете увидеть два класса StaticChild , которые расширились с StaticParent. В обоих классах есть переопределенный метод invoke(). Тогда каков будет результат main method?

Результатом вышеупомянутого набора кода является.

Calling parent class invoke() function.

Итак, здесь система вызывает методes StaticParent.invoke. Как мы уже обсуждали выше, нет никакого отношения к тому, что obj initialized.