Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Замена множественному наследованию.Содержание книги
Поиск на нашем сайте
__AddRef – нижнее подчеркивание, чтобы компилятор сам вызвал метод, когда необходимо. NET-способ кодирования интерфейсов: любому интерфейсу м.б. присвоен URL. GUID удобен тем, что его ширина фиксирована. Методы интерфейса в классе реализуются аналогично методам класса, но без override. Понятие интерфейса При программировании нередко возникает необходимость выполнить обращение к объекту, находящемуся в другом загрузочном модуле, например EXE или DLL. Для решения поставленной задачи Microsoft разработала технологию COM (Component Object Model) – компонентную модель объектов. Технология обеспечивает создание программных компонентов – независимо разрабатываемых и поставляемых двоичных модулей. Поскольку объекты различных программ разрабатываются на различных языках программирования, технология COM стандартизирует формат взаимодействия между объектами на уровне двоичного представления в оперативной памяти. Согласно технологии COM взаимодействие между объектами осуществляется посредством так называемых интерфейсов. Интерфейс – заголовки методов и описания свойств. Интерфейс = Объект – Реализация. Интерфейс сам ничего “не помнит” и ничего “не умеет делать”; он является всего лишь "разъемом" для работы с объектом. Объект может поддерживать много интерфейсов и выступать в разных ролях в зависимости от того, через какой интерфейс вы его используете. Совершенно различные по структуре объекты, поддерживающие один и тот же интерфейс, являются взаимозаменяемыми. Не важно, есть у объектов общий предок или нет. В данном случае интерфейс служит их дополнительным общим предком. Описание интерфейса По форме объявления интерфейсы похожи на обычные классы, но в отличие от классов: интерфейсы не могут содержать поля; интерфейсы не могут содержать конструкторы и деструкторы; все атрибуты интерфейсов являются общедоступными (public); все методы интерфейсов являются абстрактными (virtual, abstract). Интерфейсам принято давать имена, начинающиеся с буквы I (от англ. Interface). Не определив интерфейс ITextReader, невозможно разместить класс TTextReader в DLL-библиотеке и обеспечить доступ к нему из EXE-программы. Создавая DLL-библиотеку, мы с помощью оператора uses должны включить модуль ReadersUnit в проект библиотеки. Создавая EXE-программу, мы должны включить модуль ReadersUnit и в нее, чтобы воспользоваться описанием класса TTextReader. Но тогда весь программный код класса попадет внутрь EXE-файла, а это именно то, от чего мы хотим избавиться. Решение проблемы обеспечивается введением понятия интерфейса. Type ITextReader = interface // Методы procedure SetActive(const Active: Boolean); function GetActive: Boolean; function GetItem(Index: Integer): string; // Свойства property Active: Boolean read GetActive write SetActive; property Items[Index: Integer]: string read GetItem; default; end; Поскольку интерфейс не может содержать поля, все его свойства отображены на его методы. Поддержка интерфейса классом Интерфейс бесполезен до тех пор, пока он не реализован. Реализацией интерфейса занимается класс. Если класс реализует интерфейс, то интерфейс может использоваться для доступа к объектам этого класса. При объявлении класса имя реализуемого интерфейса записывается через запятую после имени базового класса: TTextReader = class(TObject, ITextReader) Такая запись означает, что класс TTextReader унаследован от класса TObject и реализует интерфейс ITextReader. Класс, реализующий интерфейс, должен содержать код для всех методов интерфейса. Методы QueryInterface, _ AddRef и _ Release, которые тоже должны быть реализованы. К счастью, вам нет необходимости ломать голову над реализацией этих методов, поскольку разработчики системы Delphi уже позаботились об этом. Стандартная реализация методов интерфейса IInterface находится в классе TInterfacedObject. TTextReader = class(TInterfacedObject, ITextReader) Механизм подсчета ссылок в интерфейсах Механизм подсчета ссылок на объект предназначен для автоматического уничтожения неиспользуемых объектов. Неиспользуемым считается объект, на который не ссылается ни одна интерфейсная переменная. Подсчет ссылок на объект обеспечивают методы _ AddRef и _ Release интерфейса IInterface. При копировании значения интерфейсной переменной вызывается метод _ AddRef, а при уничтожении интерфейсной переменной – метод _ Release. Вызовы этих методов генерируются компилятором автоматически. Var Intf, Copy: IInterface; Begin Copy:= Intf; // Copy._Release; Intf._AddRef; Intf:= nil; // Intf._Release; end; // Copy._Release Стандартная реализация методов _ AddRef и _ Release находится в классе TInterfacedObject. Type TInterfacedObject = class(TObject, IInterface) ... FRefCount: Integer; // Счетчик ссылок function_AddRef: Integer; stdcall; function_Release: Integer; stdcall; ... end; function TInterfacedObject._AddRef: Integer; Begin Result:= InterlockedIncrement(FRefCount); // Увеличение счетчика ссылок end; function TInterfacedObject._Release: Integer; Begin Result:= InterlockedDecrement(FRefCount); // Уменьшение счетчика ссылок If Result = 0 then // Если ссылок больше нет, то Destroy; // уничтожение объекта end; Функции InterlockedIncrement и InterlockedDecrement просто увеличивают значение целочисленной переменной на единицу. В отличие от обычного оператора сложения, они обеспечивают атомарное изменение значения переменной, что очень важно для правильной работы многопоточных программ. Var Obj: TDelimitedReader; Intf, Copy: ITextReader; Begin Obj:= TDelimitedReader.Create('MyData.del', ';'); Intf:= Obj; // Obj._AddRef -> Obj.FRefCount = 1 Copy:= Intf; // Obj._AddRef -> Obj.FRefCount = 2 ... Intf:= nil; // Obj._Release -> Obj.FRefCount = 1 Copy:= nil; // Obj._Release -> Obj.FRefCount = 0 -> Obj.Destroy Obj.Free; // Ошибка! Объект уже уничтожен и переменная Obj указывает в никуда end; Обратите внимание, что объектные переменные не учитываются при подсчете ссылок. Поэтому мы настоятельно рекомендуем избегать смешивания интерфейсных и объектных переменных. Если вы планируете использовать объект через интерфейс, то лучше всего результат работы конструктора сразу присвоить интерфейсной переменной: Var Intf: ITextReader; Begin Intf:= TDelimitedReader.Create('MyData.del', ';'); // FRefCount = 1 ... Intf:= nil; // FRefCount = 0 -> Destroy end; Если интерфейс является входным параметром подпрограммы, то при вызове подпрограммы создается копия интерфейсной переменной с вызовом метода _ AddRef: procedure LoadItems(R: ITextReader); Var Reader: ITextReader; Begin LoadItems(Reader); // Создается копия переменной Reader и вызывается Reader._AddRef end;
Копия не создается, если входной параметр описан с ключевым словом const: p rocedure LoadItems(constR: ITextReader); Var Reader: ITextRedaer; Begin ... LoadItems(Reader); // Копия не создается, метод_AddRef не вызывается end;
Интерфейсная переменная уничтожается при выходе из области действия переменной, а это значит, что у нее автоматически вызывается метод _ Release:
Var Intf: ITextRedaer; Begin Intf:= TDelimitedReader.Create('MyData.del', ';'); ... end; // Intf._Release
Расширение интерфейса Новый интерфейс можно создать с нуля, а можно создать путем расширения существующего интерфейса. Во втором случае в описании интерфейса после слова interface указывается имя базового интерфейса: IExtendedTextReader = interface(ITextReader) procedure SkipLines(Count: Integer); end; Определенный таким образом интерфейс включает все методы и свойства своего предшественника и добавляет к ним свои собственные. Несмотря на синтаксическое сходство с наследованием классов, расширение интерфейсов имеет другой смысл. В классах наследуется реализация, а в интерфейсах просто расширяется набор методов и свойств.
В языке Delphi существует предопределенный интерфейс IInterface, который служит неявным базовым интерфейсом для всех остальных интерфейсов. ITextReader = interface ~ TextReader = interface(IInterface) Описание интерфейса IInterface находится в стандартном модуле System: Type IInterface = interface ['{00000000-0000-0000-C000-000000000046}'] Function QueryInterface(constIID: TGUID; out Obj): HResult; stdcall; Function _AddRef: Integer; stdcall; Function _Release: Integer; stdcall; end; Методы интерфейса IInterface явно или неявно попадают во все интерфейсы и имеют особое назначение. Метод QueryInterface нужен для того, чтобы, имея некоторый интерфейс, запросить у объекта другой интерфейс. Этот метод автоматически вызывается при преобразовании одних интерфейсов в другие. Метод _ AddRef автоматически вызывается при присваивании значения интерфейсной переменной. Метод _ Release автоматически вызывается при уничтожении интерфейсной переменной. Последние два метода позволяют организовать подсчет ссылок на объект и автоматическое уничтожение объекта, когда количество ссылок на него становится равным нулю. Вызовы всех трех методов генерируются компилятором автоматически, и вызывать их явно нет необходимости, однако программист должен позаботиться об их реализации.
|
||||
Последнее изменение этой страницы: 2016-08-14; просмотров: 277; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.137.175.80 (0.009 с.) |