Заинтересовал тут меня полиморфизм в программировании. Так как немного знаю ABAP, решил посмотреть на примере этого языка программирования, что такое полиморфизм. Нашел несколько статей на русском языке, но в основном в них общие теоретические рассуждения или пример кода без детального объяснения. Прочитал, но понятней не стало, соответственно, решил сам разобраться на своем примере. Собственно, вот попытка ответа себе на вопрос что такое полиморфизм в ABAP Objects.
Полиморфизм ABAP позволяет использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта, то есть можно унифицировано вызывать методы, которые имеют разную реализацию, но одинаковый интерфейс. Полиморфизм работает в сочетании с наследованием, что делает возможным взаимозаменяемое использование различных классов в дереве наследования, то есть полиморфизм возникает, когда существует иерархия классов и они связаны наследованием.На практике это означает, что вызов метода приведет к выполнению реализации другого метода в зависимости от класса, который использован для вызова метода. В нашем примере, если метод speech вызывается для класса dog, то вызовется реализация метода, определенная для dog. Если метод speech вызывается для класса cat, то вызовется реализация метода, определенная для cat. Код, необходимый для вызова этих методов в экземплярах наследованных классов dog и cat, точно такой же, даже если реализация отличается.
Теперь пример.
Есть у нас желание сообщить всем какие есть животные и как они говорят. То есть делаем некий абстрактный класс “животные говорят”, который определяет название животного и как животное говорит. Пока никакой конкретики, просто абстракция.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
*---------------------------------------------------------------------* * Report ZMiasTestPolymorphism *---------------------------------------------------------------------* * Пример с полиморфизмом *---------------------------------------------------------------------* REPORT zmiastestpolymorphism. CLASS class_animal_speech DEFINITION ABSTRACT. PUBLIC SECTION. METHODS: animal ABSTRACT, speech ABSTRACT. ENDCLASS. |
Работа с объектами этого класса и его классами-наследниками должна быть одинаковой, но результат разный, в зависимости от класса животного (наследование от абстрактного класса).
Далее должна появиться конкретика через наследование (Inheriting) для собак:
1 2 3 4 5 6 |
CLASS class_dog DEFINITION INHERITING FROM class_animal_speech. PUBLIC SECTION. METHODS: animal REDEFINITION, speech REDEFINITION. ENDCLASS. |
и кошек:
1 2 3 4 5 6 |
CLASS class_cat DEFINITION INHERITING FROM class_animal_speech. PUBLIC SECTION. METHODS: animal REDEFINITION, speech REDEFINITION. ENDCLASS. |
То есть, что будет происходить для конкретного животного, определяет не какой-то атрибут, со значением ‘dog’, ‘cat’ и т.д., а сам класс.
Теперь определим класс и метод который будет выводить сообщения:
1 2 3 4 5 |
CLASS class_print DEFINITION. PUBLIC SECTION. CLASS-METHODS: print IMPORTING animal_speech TYPE REF TO class_animal_speech. ENDCLASS. |
Этот метод получит объект с конкретными методами, которые зависят от того для какого класса создан объект. Объект для класса собак будет иметь одну реализацию методов, для класса кошек – другую реализацию все тех же методов animal и speech.
Теперь сделаем реализации того, что определили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
CLASS class_dog IMPLEMENTATION. METHOD animal. WRITE: 'Собака'. ENDMETHOD. METHOD speech. WRITE: 'Гав'. ENDMETHOD. ENDCLASS. CLASS class_cat IMPLEMENTATION. METHOD animal. WRITE: 'Кошка'. ENDMETHOD. METHOD speech. WRITE: 'Мяу'. ENDMETHOD. ENDCLASS. |
Эти методы будут у объектов, созданных для конкретных классов. Мы можем передать эти объекты и получивший их метод будет вызывать методы полученного объекта, каждый раз получая разный результат.
1 2 3 4 5 6 7 8 9 |
CLASS class_print IMPLEMENTATION. METHOD print. WRITE: 'Животное'. CALL METHOD animal_speech→animal. "Тут должны быть символы тире и больше, но wordpress выводить > неправильно WRITE: 'говорит'. CALL METHOD animal_speech→speech. "Тут должны быть символы тире и больше, но wordpress выводить > неправильно ENDMETHOD. ENDCLASS. |
Что мы получили в итоге? У нас унифицированный вывод данных, вне зависимости от конкретной реализации получения этих данных.
Теперь сделаем вызов всего этого:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
START-OF-SELECTION. DATA: dog TYPE REF TO class_dog, cat TYPE REF TO class_cat. CREATE OBJECT dog. "dog = NEW #( ) или сразу без объявления DATA(dog) = NEW class_dog( ). CREATE OBJECT cat. "cat = NEW #( ) или сразу без объявления DATA(cat) = NEW class_cat( ). CALL METHOD class_print⇒print "Тут должны быть символы равно и больше, но wordpress выводить > неправильно EXPORTING animal_speech = dog. "Экземпляр класса в качестве параметра NEW-LINE. CALL METHOD class_print⇒print "Тут должны быть символы равно и больше, но wordpress выводить > неправильно EXPORTING animal_speech = cat. "Экземпляр класса в качестве параметра |
Информация о динамическом типе (class_dog), связанная с ссылочной переменой (dog), позволяет среде выполнения ABAP динамически связывать вызов метода (animal_speech->animal) с реализацией (animal), определенной в объекте (dog), на который указывает ссылочная переменная.
Всякий раз, когда метод вызывается с конкретной реализацией подкласса class_dog или class_cat, динамический тип ссылочного параметра animal_speech привязывается к одному из этих конкретных классов. Следовательно, вызовы методов ‘animal’ и ‘speech’ относятся к реализациям, предоставленным в подклассах class_dog или class_cat, а не к неопределенным абстрактным реализациям, предоставленным в классе class_animal_speech.
Мы создали конкретные объекты (для собак и кошек), которые имеют методы с разной реализацией, но наследованные от одного класса, то есть по сути определенные одинаково. Вызвали эти разные методы передав разные объекты, но все это унифицированным образом через один метод print.
Написал статью, потом нашел похожий пример тут. Там тоже про кошек и собак, но совпадение чисто случайно. Статью можно почитать, там более развернуто описано про полиморфизм.
Продолжение по теме ABAP Разименование ->* и приведение типов ?= в ABAP