Наследование и композиция в ColdFusion компонентах

ColdFusion компоненты (CFC) содержат возможности таких объектно-ориентированных языков, как Smalltalk и Java. В этой статье пойдет речь о двух самых главных взаимодействиях объектов: наследование и композиция.

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

Для многих разработчиков наследование – самая главная возможность в CFC. Наследование позволяет организовывать взаимодействия, при которых один объект расширяет возможности другого.

В реальном мире полно примеров таких взаимодействий. Например, объект "Спортивная Машина" расширяет возможности объекта "Машина", который, в свою очередь, расширяет возможности объекта "Транспорт".

Производный объект принято называть "подтип" (subtype), а его базовый объект – "надтип" (supertype). Объект "Машина" одновременно является надтипом объекта "Спортивная Машина" и подтипом объекта "Транспорт". Одним из полезных использований наследовании является повторное использование одного и того же кода. Код, который предоставляет действия по отношению к надтипу может быть использован как в подтипе, так и в любом под-подтипе (т.к. наследования могут применяться к наследуемым объектам).

 

Взаимодействие объектов при наследовании

Вы можете смоделировать взаимодействия подтипов и надтипов с помощью UML диаграммы классов, как показано ниже. Стрелка указывает направления от подтипа к надтипу.

Ключевой фразой, описывающей это взаимодействие, является фраза "относится к". Например, объект "Спортивная Машина" относится к объекту "Машина", а объект "Машина" относится к объекту "Транспорт". Приведенный ниже код создаст компоненту "Машина" (Car), которая унаследует как свойства, так и методы компоненты "Транспорт" (Vehicle):
Для компоненты "Транспорт" (Vehicle) код может выглядеть так:
Обратите внимание, что в компоненте Car.cfc осуществляются запросы к самой себе (контейнер this указывает на переменные в текущем объекте), хотя на самом деле запросы относятся к компоненте Vehicle.cfc. В этом и заключается принцип наследования – подтип (Car) может использовать методы надтипа (Vehicle).

Также обратите внимание, что Car и Vehicle обе определяют метод stop(), который у каждой компоненты выполняет разные действия. Когда подтипы или надтипы содержат методы с одинаковыми именами, то код в подтипе имеет первоочередное положение. Другими словами, методы подтипа перекрывают одноименные методы надтипа.

Давайте протестируем код для Car и Vehicle. Создадим файл TestCar.cfm, в котором укажем вызов объекта. Вызов объекта можно осуществлять одним из двух способов (как вам больше нравится):
или
Теперь запросим метод stepOnGas() в компоненте Car:
Далее запустим наш файл TestCar.cfm в браузере и увидим, что нам возвращает объект Car:

Эй! Лучше притормозить. И сделаем мы это, добавив в конце строку:
Снова запустим страницу:

Даже если методы, которые осуществляют ускорение и замедление - increaseSpeed() и decreaseSpeed() – принадлежат Vehicle.cfc, то Car.cfc наследует их, поскольку является подтипом Vehicle.

Обратите внимание, что когда мы запрашиваем myCar,stop(), то будет выполнен метод stop() из Car.cfc, а не из Vehicle.cfc. Это наглядный пример перекрывания одноименных методов.

Укажите следующий код в конце TestCar.cfm и снова запустите его:
Вот то, что мы увидим после выполнения метода stop():

 

Взаимодействие объектов при композиции

Наследование очень мощная штука, пока нам нужно взаимодействие "относится к" между двумя объектами. Обычно, один объект содержит другой объект для осуществления каких-то своих свойств. При таком взаимодействии, ключевой фразой будет слово "содержит". Например, объект "Человек" (Person) содержит объект "Адрес" (Address). Такие взаимодействия между объектами называются "композиция".

В случае с объектом Person без использования композиции вы может смоделировать его так:
Конечно, нам понадобиться написать методы для получения и установления индивидуальных переменных. Это не сложно.

Ниже приведен пример кода, позволяющий получать и устанавливать свойство address1:

Точно таким же образом, нам придется создать методы для всех остальных свойств. Теперь представим, что у нас есть еще одна компонента "Место Проживания" (Venue):
Хм … Объекту Venue также нужна информация об адресе человека. Это означает, что в обоих компонентах Person и Venue вы укажите один и тот же код для получения и установки адреса. Лучшим решением этой задачи будет создание отдельной компоненты "Адрес" (Address) и отнести ее к объекту Person с помощью композиции. Следующая UML диаграмма классов показывает это взаимодействие:

Компонента Address.cfc проста:
Теперь, когда объекту Person (или любой другой компоненте) понадобиться установить адрес, то мы можем использовать один объект Address, выполнив в нем метод new(). Затем, полученный объект мы можем установить как свойство объекта Person.

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

Код для файла TestPerson.cfm следующий (обратите внимание, что на картинке выше форма аккуратно оформлена с помощью html тега <table>. В коде ниже этого тега нет, чтобы показать Вам только программный код):
Атрибут action указывает на страницу ProcessUserForm.cfm, но перед тем как обратиться к коду этой страницы, давайте переработаем Person.cfc:
Обратите внимание, что в методе new() аргумент address принимает тип Address, т.е. в качестве значения этого аргумента ожидается объект Address.

Определив компоненты Person.cfc и Address.cfc обратимся к странице ProcessUserForm.cfm. Тут кода не много:

Когда вы заполните и отправите форму, то в результате увидите вывод тега <cfdump>:

Как видим, компоненты – интригующая возможность ColdFusion. Они предоставляют мощные возможности для повторного использования кода и инкапсуляции. Используя наследование, вы можете указать код в подтипах и использовать его в подтипах. Принцип наследование отлично работает тогда, когда компоненты взаимодействуют между собой как родитель и ребенок.

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

Понимание того, как объекты взаимодействуют друг с другом – самое важное в использовании ColdFusion компонент.

 


Источник: Using Inheritance and Composition in ColdFusion Components

 


Hosted by uCoz