Полиморфизм в греческом языке означает "много форм". В CFC полиморфизм означает, что мы можем вызывать один и тот же метод, передавая ему разные типы CFC. Это также означает, что мы можем передавать в метод различные типы CFC как значение аргумента, и позволить методу отвечать в зависимости от типа переданной ему CFC.
Такие вещи, как полиморфизм лучше показывать, чем объяснять. Поэтому давайте создадим несколько CFC, чтобы мы наглядно могли убедиться, каким полезным полиморфизм может быть.Создаем компоненты
Чтобы продемонстрировать полиморфизм в компонентах, создадим иерархию компонент, отображающую животных. На самом высоком уровне компонента Животное (Animal). Это абстрактная компонента, которая содержит методы и данные, общие для всех видов животных. Здесь находится размер и тип животного, а также определены абстрактные методы eat() и makeNoise(), которые должны быть переопределены в подтипе.
Компонента Млекопитающее (Mammal) является подклассом компоненты Animal. Также как и Animal, назначение Mammal заключается в том, чтобы хранить данные и методы, общие для всех млекопитающих. В этом примере, Mammal не выполнять много действий, но мы можем представить, что тут есть такие методы как, например, growHair(). Mammal - абстрактная компонента, как и Animal. Мы никогда не создаем шаблонов абстрактных компонент, но создаем шаблоны конкретных подтипов абстрактных компонент. Например, Mammal в действительности не существует в реальном мире и является обобщением. В настоящем мире есть такие виды млекопитающих, как, например, зебра или мышь. В ColdFusion нет средств, которые позволяли бы обозначать компоненту как абстрактную, но все-таки мы можем просто учитывать эту идею.Далее, создаем компоненты, которые наследуют Mammal: Мышь (Mouse), Зебра (Zebra) и Кошачьи (Feline). Mouse и Zebra – конкретные компоненты, что означает, что мы можем создавать их шаблоны. В настоящем полиморфизме оба объекта Mouse и Zebra обрабатывают методы eat() и makeNoise() по своему. Так оно и должно быть: когда они издают звук, то Мышь (Mouse) пищит, а Зебра (Zebra) лает (да, зебра на самом деле лает, а не ржет).
Кошачьи (Feline) – еще один абстрактный класс, который должен содержать такие методы, применимые ко всем кошачьим, как purr(). Наконец, конкретными подтипами Feline являются Тигр (Tiger) и Домашняя кошка (Housecat). И еще раз, Tiger и Housecat по своему обрабатывают методы eat() и makeNoise().Всю описанную выше модель мы можем теперь увидеть на UML диаграмме классов:
А код для создания всех этих компонентов будет таким:Полиморфизм в действии
Теперь давайте посмотрим на полиморфизм в действии. Начнем с того, что создадим шаблоны четырех конкретных компонент из нашей иерархии:
Теперь, когды мы создали шаблоны всех четырех компонент, мы можем в каждой из них вызвать метод makeNoise() и посмотреть, что произойдет:Голос Домашней кошки: #aHousecat.makeNoise()# Голос Тигра: #aTiger.makeNoise()# Голос Мыши: #aMouse.makeNoise()# Голос Зебры: #aZebra.makeNoise()#В результате мы получили какофонию звуков: мяуканье, рев, писк и лай. Поскольку наша абстрактная компонента Animal требует, чтобы ее подтипы переопределяли метод makeNoise(), то каждый вид животного отвечает присущим ему голосом. Полиморфизм в действии! Таким образом, мы узнали, что даже если создадим 50 различных подтипов компоненты Animal, то запрос makeNoise() в каждом из них вернет разный ответ. Мы снова сможем убедиться в этом, вызвав метод eat() в объектах Mouse и Zebra:
Мышь ест: #aMouse.eat()# Зебра ест: #aZebra.eat()#Ответ будет "сыр" и "трава" соответственно.
Усложним задачу
Теперь давайте посмотрим на более сложный пример полиморфизма. Метод eat() обрабатывается в объектах Housecat и Tiger по разному. Поэтому, мы должны передать объект Animal в метод eat() для Housecat или Tiger. Вот так:
Это означает, что метод eat() принимает объект Animal или любой подтип этого объекта, как правильный аргумент. Таким образом, мы имеем полное право, передать объект Zebra в метод eat(). Забавная ситуация получилась. Но если мы передадим в метод eat() какой-нибудь посторонний объект, например, Машина (Car), то в ответ получим ошибку, т.к. объект Car не является подтипом Animal. А вот Домашняя кошка может съесть Зебру:Домашняя кошка ест Зебру: #aHousecat.eat(aZebra)#Но давайте приведем более подобающий пример:
Домашняя кошка ест Мышь: #aHousecat.eat(aMouse)#Теперь это похоже на правду :)
Заключение
Полиморфизм очень мощный и полезный элемент объектно-ориентированных языков. Теперь, используя компоненты, ColdFusion разработчики могут пользоваться этой мощью. Поначалу полиморфизм не просто понять, но немного практики и вы очень легко станете обращаться с ним. Надеюсь, что приведенный здесь пример подтолкнет вас к каким-либо идеям, чтобы использовать полиморфизм в ваших собственных проектах.
© 2002-2005 г. Вадим Пушкарев