Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы Java и C# технологии.doc
Скачиваний:
171
Добавлен:
01.03.2016
Размер:
3.04 Mб
Скачать
      1. Динамическое приведение типов

В ранее рассмотренном разделе "Использование интерфейсов" для получения ссылки на интерфейс, реализуемый объектом, применяется операция asязыка C#. Если объект не поддерживает данный интерфейс, будет возвращенапустая ссылка(null).

В большинстве случаев у нас есть или можно создать экземпляр объекта, а потом применить к нему операцию as, но делать так не совсем рационально. Во-первых, создание объекта может потребовать больших затрат, тем более что неизвестно, будем ли он использован в дальнейшем. Во-вторых, возможно, что объект всё равно не удастся создать, потому что тип может быть абстрактным классом или интерфейсом.

В предыдущем примере чтобы определить, что тип, считанный из сборки, реализует необходимый интерфейс, был использован метод IsAssignableFromклассаType, который в качестве аргумента принимает объект классаType.

Класс Typeимеет ещё один метод со схожей функциональностью –IsInstanceOfType. В отличие отIsAssignableFromон принимает в качестве аргумента не объектType, а экземпляр конкретного объекта. МетодIsInstanceOfTypeопределяет, является ли тип объекта, переданного в аргументе, наследником типа, для которого этот метод вызван. Иначе можно это сформулировать вот так:

type.IsInstanceOfType(obj) = obj.GetType().IsAssignableFrom(type)

Примечание. В Java-программистов похожая по смыслу операцияinstanceofимеет такие же аргументы, но только в другом порядке. Она применяется к объекту и принимает в качестве аргумента имя типа. ВJavaоперацияinstanceofсовпадает по смыслу с операциейisв С#.

      1. Новые механизмы абстракции

После рассмотрения методов исследования типов (методов рефлексии), встает вопрос – "Какое новое качество могут принести методы рефлексии в программы. Дают ли они в руки разработчика принципиально новые возможности?" Ответ на этот вопрос положительный.

Следует напомнить, что в С++ (а может и во всей идеологии ООП) существуют два принципиально разных подхода к разработке абстрактных алгоритмов и абстрактных типов данных. Первый подход основан на использовании шаблонов, а второй – на наследовании и виртуальных методах.

Формулируя алгоритм с помощью абстрактных типов данных (шаблонов), программист предполагает наличие определённых свойств у параметров шаблона – типов, которые будут "подставлены" в шаблон. Конкретная реализация алгоритма становится ясной тогда, когда становятся известны типы-параметры шаблона, т.е. во время компиляции программы, использующей шаблон – конкретизация при компиляции.

Формулируя алгоритм с помощью абстрактных (виртуальных) методов класса, разработчик откладывает окончательную реализацию алгоритма на время исполнения программы. Именно тогда, во время исполнения, решается то, какие реальные методы будут участвовать в работе алгоритма. Это зависит от того с какими конкретными объектами придётся работать алгоритму. Можно сказать, что виртуальные методы конкретизируются вruntime– конкретизация времени исполнения.

Однако возможность по виртуализации методов классов и их конкретизация во времени исполнения программы делает естественным желание получить то же и по отношению к полям объектов и к абстрактным структурам данных, когда они конкретизируются не при компиляции, а во время исполнения.

Всё это позволяет сделать Reflection. Таким образом,Reflection– это виртуализация всех элементов программы.

Теперь разработчику позволительно формулировать алгоритмы подобные таким:

  1. "Найди в данной структуре поле, обозначающее цену товара, и вернуть его". Для этого перебираем все поля класса, в поисках поля типа Currency. Для этого даже не надо знать имя поля. Если известно, что поле такого типа есть и оно одно – этого достаточно.

  2. "Связать поля данной структуры с аргументами требуемой хранимой процедуры на основе типов и имён полей и параметров".

  3. "Вывести на консоль поля c атрибутом "видимый" (см. пример выше).

  4. "Предложить пользователю выбрать класс, заполнить параметры его конструктора класса и создать экземпляр этого класса".

Таким образом, разработчику стало доступно то, что раньше мог делать только компилятор. Эти новые возможности позволяют породить совершенно новые классы алгоритмов, новые подходы к программированию, что, в свою очередь, принесёт новое качество в ваши программы.