Файл: 14. Компонентная разработка приложений. Введение в компонентные модели.pdf
ВУЗ: Университет управления «ТИСБИ»
Категория: Учебное пособие
Дисциплина: Объектно-ориентированное программирование
Добавлен: 20.10.2018
Просмотров: 1307
Скачиваний: 9
public void addKeyListener(KeyListener kl) { . . . };
public void removeKeyListener(KeyListener kl) { . . . };
public void addMouseListener(MouseListener ml) { . . . };
public void removeMouseListener(MouseListener ml) { . . . };
Информация
о
всех
свойствах
компонентного
класса
и
зарегистрированных событиях сохраняется в файле и с помощью механизма
отражения доступна в процессе визуального создания программы. Здесь
также используется такое важное свойство Bean-компонентов, как
сохраняемость (persistence), т.е. способность компонентов записывать себя
во внешние файлы с восстановлением своей структуры в более позднее
время. Это свойство обеспечивается механизмом сериализации, который
является стандартным для всех объектов Java, реализующих интерфейс
Serializable. Этот механизм превращает объект в поток байтов, помещаемый
во внешний файл. Очень важно, что механизм сериализации позволяет
сохранять и восстанавливать объектную структуру любой сложности, т.е. со
всеми внутренними объектными свойствами.
В заключение рассмотрим компонентную модель платформы .NET. Эта
платформа в основном предназначена для разработки приложений для
систем семейства Windows. Основу этой технологии составляет библиотека
классов Framework Class Library, которая в настоящее время включает в
себя несколько тысяч классов, с помощью которых можно создавать
практически любые типы Windows-приложений.
Одной из особенностей процесса разработки .NET-приложений является
языковая независимость (относительная, конечно): исходный текст можно
написать на любом языке, поддерживающем данную технологию (C#, J#, VB,
C++), после чего соответствующий компилятор переводит этот текст в
универсальное промежуточное представление. Это представление
описывается с помощью специального языка IL (Intermediate Language),
немного похожего на язык ассемблера. После этого отдельные IL-модули
могут объединяться в так называемую сборку (assembly), которая
представляет собой единицу распространения программы. Интересно, что
сборка помимо кода на IL-языке содержит метаданные с полным описанием
используемых в программе типов и классов. При запуске программы на
выполнение IL-код переводится на машинный язык конкретного процессора
и выполняется. Этими процессами управляет специальное средство .NET-
технологии – так называемая Common Language Runtime (CLR,
общеязыковая среда выполнения).
Компонентная модель платформы .NET аналогична рассмотренным
ранее моделям языков Java и Delphi. При описании класса вводятся закрытые
поля данных и открытые свойства для определения методов доступа к этим
полям. Описание свойства должно включать объявление одного или двух
методов доступа с обязательными именами get и set.
Например:
public class MyClass
{ private int myfield; // закрытое поле
public int MyField // соответствующее свойство
{ get { return myfield; } // метод доступа
{ set { myfield = value; } // метод доступа
}
. . . другие поля и их свойства . . .
}
Аналогично другим языкам, механизм свойств позволяет организовать
более строгий и контролируемый доступ к значениям внутренних свойств
объектов.
Как уже отмечалось выше, компонент как строительный блок
приложения должен обеспечивать реакцию на определенные события.
Обработка событий в .NET-приложениях основана на использовании
указателей на функции-обработчики, но по сравнению с пакетом Delphi эти
указатели реализованы более надежным способом – с помощью специальных
объектов, называемых делегатами (delegate). Объект-делегат может хранить
указатель на функцию только конкретного заранее заданного типа, что
позволяет организовать контролируемый вызов методов и тем самым
повышает надежность приложения.
Базовым классом для реализации делегатов является класс
MulticastDelegate, в котором вводится возможность хранения любого числа
указателей на функции и все необходимые для этого методы. На основе этого
класса создаются пользовательские дочерние классы, объекты которых и
выполняют всю работу по обращению к необходимым функциям. Поскольку
все вызовы таких функций выполняются динамически при работе
приложения, то без использования среды выполнения CLR обойтись
невозможно.
Класс-делегат описывается неявно с помощью служебных слов,
например (в языке C#) – с помощью директивы delegate. Синтаксис описания
делегатов отличается от привычного описания классов, поскольку часть
работы возложена на компилятор. При описании класса-делегата указывается
прототип метода, на который будут ссылаться объекты-экземпляры этого
класса. Например, следующий делегат предназначен для вызова любых
методов, которые имеют ровно один параметр строкового типа и не
возвращают результат (void):
delegate void MyDelegat (string st);
После этого надо создать объект-делегат с помощью неявного
конструктора, передав ему в качестве параметра имя метода, на который
должен ссылаться объект-делегат:
MyDelegat myDel = new MyDelegat (myObj.MyMetod);
Здесь myObj – объект класса, в котором реализован пользовательский
метод с именем MyMetod. Для нашего примера этот метод обязательно
должен иметь ровно один параметр строкового типа! Если попытаться
передать конструктору метод с другой сигнатурой, компилятор выдаст
сообщение об ошибке.
Пусть для наглядности этот метод MyMetod просто лишь выводит на
экран текстовую строку, передаваемую ему через входной параметр st. Тогда
для вызова этого метода с помощью делегата достаточно оформить
следующую простую конструкцию:
myDel (“ Hello from delegate”);
Конечно, в данном примере использование делегатов кажется
надуманным, поскольку метод MyMetod можно вызвать непосредственно.
Однако для реализации обратных вызовов, возникающих при выполнении
программы этот механизм весьма удобен. Именно по этой причине он и
используется при обработке событий. При этом важным моментом в
механизме делегатов становится возможность объединения объектов-
делегатов в списки. Для добавления и удаления элементов в эти списки
можно использовать методы Combine и Remove базового класса
MulticastDelegate. Для удобства использования этих методов в языке C#
переопределены операторы += и -= . Вместо них компилятор подставляет
вызовы методов Combine и Remove. Например, если вместе с методом
MyMetod объявить другой метод MyMetod2 с такими же параметрами (в
данном случае – с одним параметром строкового типа), то его можно
добавить в цепочку делегатов с помощью следующей конструкции:
myDel += myObj.MyMetod2;
После этого указанное выше обращение к делегату приведет к вызову
уже двух разных методов.
Обработка событий встраивается в компоненты следующим образом.
Прежде всего, в классе компонента объявляется закрытое поле-делегат,
через которое должна устанавливаться связь с объектом-делегатом. Потом в
классе вводится специальное открытое свойство с двумя методами, которые
пользователи компонента могут использовать для добавления и удаления
событий в списке вызова делегата. Поскольку эти операции являются
достаточно стандартными, в язык С# введена специальная директива event, с
помощью которой в классе компонента и вводятся необходимые
составляющие:
class MyComponent: ParentComponent
{ public event MyDelegat MyEvent;
. . . . . . . . . };
После этого пользователи компонента должны создать его экземпляры и
добавить обработчики события MyEvent следующим образом:
MyComponent myComp = new MyComponent ( );
myComp += new MyDelegat (myComp.MyMetod);
В заключение отметим, что для создания полноценных компонентов
необходимо придерживаться ряда простых рекомендаций по оформлению
делегатов и методов-обработчиков событий.