пятница, 27 января 2012 г.

Объектно-ориентированное программирование. Полиморфизм

В данной статье хотелось бы рассказать об одном из китов объектно-ориентированного программирования – полиморфизме. Что это такое, и как его применять на практике.

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

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

Приведу наглядный пример. Все садовые деревья плодоносят, независимо от сорта дерева. Отсюда вытекает, что единым интерфейсом является объект «дерево» с методом «созревание плодов». А вот как, и каким способом созревает плод, является индивидуальной реализацией каждого сорта отдельно. Перенесем выше сказанное на программный язык.
Создадим класс GardenTree, в котором реализуем только один метод «maturation»:

package my.polimorfism;

public class GardenTree {
      
       public void maturation() {
            
             System.out.println("Parent class: maturation.");
       }
}

Далее создадим два класса наследующих класс GardenTree, и переопределяющих метод maturation родительского класса:

package my.polimorfism;

public class Apple extends GardenTree {

       public void maturation() {
            
             System.out.println("Maturation apple.");
            
       }
}

package my.polimorfism;

public class Cherry extends GardenTree {

       public void maturation() {
            
             System.out.println("Maturation cherry.");
            
       }
}
Ну и собственно создаем класс, в котором реализуется идеология полиморфизма:

package my.polimorfism;

public class App
{
    public static void ripening_fruit(GardenTree i) {
       i.maturation();
    }
   
       public static void main( String[] args ) {
            
             GardenTree apple = new Apple();
             GardenTree cherry = new Cherry();
            
             ripening_fruit(apple);
             ripening_fruit(cherry);
    }
}

Вызов метода maturation классов Apple и Cherry, через единый метод и является полиморфизмом.
Мы можем без проблем добавить класс Pear, в котором будет своя реализация метода maturation.

package my.polimorfism;

public class Pear extends GardenTree {

       public void maturation() {
            
             System.out.println("Maturation pear.");
            
       }
}

И вызвать его метод maturation, через единый интерфейс ripening_fruit.

                               GardenTree pear = new Pear();
                               ripening_fruit(pear);

При полиморфизме мы не плодим метод ripening_fruit для каждого сорта дерева, а передаем в аргумент данного метода базовый класс, вместо дочернего класса.


Если внимательно присмотреться к нашему коду, то можно увидеть, что мы используем восходящее преобразование.

                               GardenTree apple = new Apple();
                               GardenTree cherry = new Cherry();
                               GardenTree pear = new Pear();

Интеграция ссылки объекта как ссылки на базовый тип называется восходящим преобразованием.

Исходный код программы можно скачать здесь.

7 комментариев:

  1. Здравствуйте, Евгений.
    Спасибо Вам за статью. Я недавно начал изучать Java, и у меня есть вопрос. Если в классах Apple и Cherry есть свои методы, то GardenTree их уже не увидит, т.е. придется писать:
    Apple apple = new Apple();
    Cherry cerry = new Cherry();
    Т.е. полиморфизм имеет смысл только тогда, когда используются абсолютно однотипные классы?

    ОтветитьУдалить
    Ответы
    1. Добрый день.
      Да, вы правильно понимаете. Полиморфизм как бы группирует однотипные классы под одним "интерфейсом".

      Удалить
    2. Можно попробовать обратиться к методам класса Apple через приведение к типу Apple класса GardenTree так как Apple является его потомком, как-то так:

      GardenTree apple = new Apple();
      ((Apple) apple).some_method

      хотя могу ошибаться..

      Удалить
  2. Объясните, пожалуйста, эту конструкцию:
    public static void ripening_fruit(GardenTree i) {

    i.maturation();

    ОтветитьУдалить
  3. Эта конструкция обозначает следующее:
    создается статический метод (который ничего не возвращает) и в него передается аргумент(переменная) типа GardenTree. i - название этой переменной.
    конструкцией i.maturation(); мы вызываем метод maturation класса GardenTree.

    ОтветитьУдалить
  4. Топ легальных азартных клубов поддерживает бренды, где можно выступать на средства. Площадки шансы похвастаться резвыми выплатами рейтинг игровых автоматов онлайн. Большинство просят прохождение верификации. Среди игорных ресурсов возможно отыскать свежие порталы с минимальным депозитом от 1 $. Отличный развлечения от заморочек за наименьшую необходимую сумму — что может быть лучше?

    ОтветитьУдалить
  5. Посевы на данных площадках я советую создавать бесплатные ссылки для продвижения сайта как колличество раза ежемесячно. Это вероятность найти настоящих посетителей и получить качественные переходы на интернет-сайт. Все перечисленные способы относятся к крауд-маркетингу, а он густо связан с нативной рекламой.

    ОтветитьУдалить