
- •1. Понятие модуля. Принципы модульного программирования. Понятие объекта как динамического модуля.
- •2. Понятие класса. Понятие метода. Представление метода в виде обычной процедуры. Понятие конструктора и деструктора.
- •3. Понятие свойства. Методы получения и установки значений свойств. Свойства-массивы (в некоторых языках программирования). Индексаторы (в некоторых языках программирования).
- •Информация о типе времени выполнения программы
- •5. Классы в программных модулях. Атрибуты доступа к элементам объектов. Термин «инкапсуляция».
- •Термин «инкапсуляция»
- •Virtual – в базовом классе
- •7. Понятие ссылки на метод объекта (или делегата – в зависимости от языка программирования). Понятие события. Применение ссылок на методы для расширения объектов.
- •8. Понятие метакласса (в некоторых языках программирования). Методы, применяемые к классам. Виртуальные конструкторы (в некоторых языках).
- •Понятие метакласса (в некоторых языках программирования)
- •Виртуальные конструкторы (в некоторых языках)
- •3) Finally – вызвать free.
- •Если глобально-уникальный идентификатор назначается интерфейсу, то он записывается после ключевого слова interface и заключается в квадратные скобки, например:
- •Microsoft Visual Studio
- •Import Network;
- •Var Stat: SocketStat;
- •Var SocketStatCollection: … ;
- •Конструкторы и деструкторы
- •Стандартные конструкторы
- •Создание объектов по значению (на стеке) и по ссылке (в динамической памяти)
- •Операторы new и delete
- •Размещающий оператор new
- •Порядок конструирования и разрушения объектов
- •Вложенные определения классов
- •«Друзья» класса
- •Статические члены класса
- •19. Перегрузка бинарных операторов. Перегрузка унарных операторов. Перегрузка операторов преобразования типа.
- •Индексаторы
- •Механизм вызова событий
- •Создание пользовательских обобщенных коллекций
- •Создание обобщенных интерфейсов
- •Несколько слов о вложенных делегатах
- •25. Понятие итератора в языке c#. Оператор foreach. Оператор yield.
- •И напоследок... Блок finally
- •26. Понятие атрибутов в языке c#. Создание пользовательских атрибутов. Анализ атрибутов во время выполнения программы. Понятие рефлексии (reflection) в языке c#. Сериализация объектов.
- •Что такое метаданные и зачем они нужны?
- •1. Метаданные в .Net обязательны и универсальны.
- •2. Метаданные в .Net общедоступны.
- •3. Метаданные в .Net исчерпывающи.
- •4. Метаданные в .Net расширяемы.
- •5. Метаданные в .Net конструируемы программно.
- •Получение экземпляра класса Type
- •Динамическая загрузка сборок
- •Динамическая загрузка типов
- •Исследование типа
- •Характеристики типа как целого
- •Члены класса
- •Исследование объекта
- •Динамическое создание объекта и вызов методов
- •Создание объекта по его типу
- •Декларативное программирование
- •Новые механизмы абстракции?
- •Динамическое создание типов
- •Роль графов объектов
- •Formatter сериализации
- •XmlSerializer
- •Интерфейсы iFormatter и iRemotingFormatter
- •Точность типов среди форматеров
- •28*. Ооп в языке программирования Smalltalk. Достоинства и недостатки этого языка в сравнениии с языком программирования c#.
Точность типов среди форматеров
Наиболее очевидное отличие между тремя форматерами связано с тем, как граф объектов сохраняется в потоке (двоичном, SOAP или XML). Следует знать также о некоторых более тонких отличиях, в частности — каким образом форматеры добиваются точности типов (type fidelity).
Когда используется тип BinaryFormatter, он сохраняет не только данные полей объектов из графа, но также полное квалифицированное имя каждого типа и полное имя определяющей его сборки (имя, версия, маркер общедоступного ключа и культура). Эти дополнительные элементы данных делают BinaryFormatter идеальным выбором, когда необходимо передавать объекты по значению (т.е. полные копии) между границами машин для использования в .NET-приложениях.
Форматер SoapFormatter сохраняет трассировки сборок-источников за счет использования пространства имен XML. Например, вспомните тип Person, определенный в предыдущей статье. Если понадобится сохранить этот тип в сообщении SOAP, вы обнаружите, что открывающий элемент Person квалифицирован сгенерированным параметром xmlns. Взгляните на следующее частичное определение, обратив особое внимание на пространство имен XML под названием a1:
<a1:Person id="ref-1" xmlns:a1=
"http://schemas.microsoft.com/clr/nsassem/SimpleSerialize/MyApp%2C%20
Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<isAlive>true</isAlive>
<personAge>21</personAge>
<fName id="ref-3"x/fName>
</a1:Person>
Однако XmlSerializer не пытается предохранить точную информацию о типе, и потому не записывает его полного квалифицированного имени или сборки, в которой он определен. Хотя на первый взгляд это может показаться ограничением, причина состоит в открытой природе представления данных XML. Ниже показано возможное XML-представление типа Person:
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2 001/XMLSchema">
<isAlive>true</isAlive>
<PersonAge>2l</PersonAge>
<FirstName />
</Person>
Если необходимо сохранить состояние объекта так, чтобы его можно было использовать в любой операционной системе (Windows ХР, Mac OS X и различных дистрибутивах Linux), на любой платформе приложений (.NET, Java Enterprise Edition, COM и т.п.) или в любом языке программирования, придерживаться полной точности типов не следует, поскольку нельзя рассчитывать, что все возможные адресаты смогут понять специфичные для .NET типы данных. Учитывая это, SoapFormatter и XmlSerializer являются идеальным выбором, когда требуется гарантировать как можно более широкое распространение объектов.
27. Особенности языков программирования Oberon, Component Pascal, Zonnon. Сравнительный анализ языков Oberon, Component Pascal, Zonnon, Delphi, C++, Java, C#.
Оберон является если не минимальным, то, во всяком случае, одним из самых малых по объёму языков программирования высокого уровня. Программа на Обероне представляет собой набор модулей. В общем виде модуль имеет вид:
MODULE Имя;
IMPORT СписокИмпорта;
Определения;
BEGIN
Операторы
END Имя.
Типы данных ограничены следующим набором: типы-массивы ARRAY, типы-записи RECORD, процедурные типы PROCEDURE, типы-указатели POINTER. Указатель может быть объявлен только на массив или запись.
Язык поддерживает традиционный набор конструкций: условный оператор IF, оператор выбора CASE, циклы (с предусловием — WHILE, с постусловием REPEAT..UNTIL, безусловный — LOOP, со счётчиком — FOR). Прописные и строчные буквы в идентификаторах различаются, все зарезервированные слова пишутся большими буквами. Все языковые конструкции, кроме цикла REPEAT..UNTIL заканчиваются ключевым словом END и допускают расположение внутри нескольких операторов без использования составного оператора BEGIN..END. Отсутствуют безусловные переходы.
Из соображений «достаточного минимума» в язык не были включены методы (процедуры и функции, связанные с типом), так как этот механизм в самом общем виде легко смоделировать, создавая в записях в языке Оберон поля процедурного типа и присваивая им процедуры, соответствующие методам. Таким образом, в Обероне минимальными средствами поддерживается объектно-ориентированное программирование для упрощения процесса трансляции кода и ускорения этого процесса.
Наследником Оберона стал Component Pascal – его компонентное расширение. Компонентно-ориентированное программирование (КОП) возникло как своего рода дисциплина, т.е. набор определенных ограничений, налагаемых на механизм ООП, когда стало ясно, что бесконтрольное использование ООП приводит к проблемам с надежностью больших программных комплексов.
Это т.наз. проблема хрупких базовых типов; проблема может проявиться при попытке изменить реализацию типа-предка, когда может оказаться, что изменить реализацию типа-предка даже при неизменных интерфейсах его методов невозможно, не нарушив корректность функционирования типов-потомков.
Можно сказать, что КОП — это такое ООП, которое подчинено требованиям безопасности "старого" структурного и модульного программирования примерно в том виде, в каком эти требования были реализованы в классической Модуле-2 (в отличие от языков типа Smalltalk, в которых ООП является основным механизмом, который применяется без ограничений).
КОП можно описать примерно такой формулой:
КОП = ООП + модульность (включая упрятывание информации и позднее связывание модулей, т.е. возможность подгружать необходимые модули в процессе выполнения программы, а не заранее, как это обычно делается в старых системах программирования)
+ безопасность (статический контроль типов переменных и автоматическое управление памятью) - наследование реализации через границы модулей.
Последняя строчка означает, что в КОП запрещено наследование от типов, реализованных в других модулях; наследовать можно только абстрактным, чисто интерфейсным типам (помеченных атрибутом ABSTRACT в Компонентном Паскале).
Между прочим, Оберон-2 не удовлетворяет в полной мере требованиям КОП: в нем любой тип может быть расширен. Это делает программы, написанные на нем, уязвимыми для проблемы хрупких базовых классов. Именно для устранения этой "дыры" в системе безопасности Оберона-2 и были в первую очередь предприняты модификации языка, реализованные в Компонентном Паскале. В классическом Обероне тоже можно расширять любой тип, но там нет методов, так что и проблема менее остра.
Zonnon — язык программирования общего назначения, основанный на языкe Modula-2, и поддерживающий активные объекты, появившиеся в Active Oberon. В языке введена новая парадигма программирования — композиционная модель. Используется сборка мусора, содержатся синтаксические средства объектного программирования, организации параллельных вычислений, переопределения операторов и обработки исключений. В современной версии компилятора ETH в языке появилась возможность решать задачи линейной алгебры с синтаксисом похожим на matlab. Компилятор языка создан вне Microsoft и полностью интегрирован в Visual Studio совместно с другими языками платформы .NET.
Язык регистро-зависимый — разница в регистре букв в идентификаторах приводит к их различию. Ключевые (зарезервированные) слова являются зарезервированными при написании либо всех букв в верхнем, либо всех букв в нижнем регистре. То есть accept и ACCEPT — ключевые слова, а вот AcCePt — просто допустимый идентификатор.
Из особенностей можно отметить использование знака # в качестве символа операции «не равно» (как в Модуле-2), а также наличие операции ** — «возведение в степень», — возвращённой в строй после многолетнего забвения из языка Фортран.
Язык включает набор примитивных типов — несколько числовых, в том числе беззнаковое целое, несколько вещественных, строковый тип (стандартные языковые средства рассматривают строки как немодифицируемые), символьный, логический. От типов-диапазонов отказались, но типы-перечисления сохранили и активно используют. Тип-множество (SET) сохранился, но стал менее универсальным — множества теперь могут состоять только из целых чисел в диапазоне от нуля до некоторого верхнего предела, определяемого реализацией. Примитивные типы и множества могут использоваться в программе с модификаторами размера — если в описании предмета или объекта за именем типа в фигурных скобках следует число, оно воспринимается как количество битов, которое необходимо отвести под значение. Впрочем, эта возможность (точнее, конкретные значения размера, допустимые для каждого из типов) является системно-зависимой, так что в программах, претендующих на переносимость, её применение не может быть рекомендовано.
Массивы описываются так же, как в Обероне — тип-массив может иметь неограниченный размер по любому набору размерностей, при создании реального массива его размеры указываются явным образом. Индексы массива могут быть либо целыми числами (нижняя граница — всегда нуль) либо относиться к перечислимому типу.
Общая структура программы, модулей, разделение модуля на модуль определений и модуль реализации, правила записи синтаксических конструкций заимствованы из Модулы-2 практически без изменений. Поддерживается «длинная» конструкция условного оператора IF-THEN-ELSIF-ELSE-END, все типы циклов, имеющиеся в Модуле: REPEAT-UNTIL, WHILE, FOR, LOOP, конструкция выбора CASE. Из Паскаля возвращены в язык стандартные примитивные операции ввода-вывода Write, WriteLn, Read, ReadLn (которые в Модуле-2 были вынесены в стандартную библиотеку).
Дополнительно в язык внесены:
-Средства ООП: объявление классов (используется ключевое слово object), методы (описываются целиком внутри описания класса), спецификаторы видимости для полей и методов private и public, отдельное описание ООП-интерфейсов и возможность явного указания реализации интерфейсов классом.
-Свойства — псевдополя классов с полностью контролируемым доступом.
-Индексаторы — возможность описания классов, экземпляры которых внешне ведут себя как массивы.
-Средства обработки исключений.
-Переопределение существующих операторов и объявление новых.
-Средства параллельного программирования: языковыми средствами могут быть созданы параллельно исполняющиеся фрагменты программы, взаимодействие которых происходит через протоколы — специфический тип данных, задаваемый с помощью модифицированного РБНФ-описания формат сообщения, которое будет передаваться.
Основным концептуальным новшеством Zonnon, по сравнению с Модулой и Обероном, стало введение активных объектов. В большинстве языков программирования объект — это просто набор данных и методов обработки, который используется программой по мере необходимости. Активные объекты, помимо этого, имеют собственное поведение, то есть с каждым активным объектом связан свой, независимый поток исполнения, который взаимодействует с другими потоками через языковые средства обмена, по описанным для них протоколам. В Zonnon появилась возможность описывать языковыми средствами активные объекты и порядок их взаимодействия, что позволяет при необходимости формировать программу в виде набора независимо работающих и взаимодействующих друг с другом активных объектов.
Object Pascal — результат развития языка Турбо Паскаль, который, в свою очередь, развился из языка Паскаль. Паскаль был полностью процедурным языком, Турбо Паскаль, начиная с версии 5.5, добавил в Паскаль объектно-ориентированные свойства, а в Object Pascal — динамическую идентификацию типа данных с возможностью доступа к метаданным классов (то есть к описанию классов и их членов) в компилируемом коде, также называемом интроспекцией — данная технология получила обозначение RTTI. Так как все классы наследуют функции базового класса TObject, то любой указатель на объект можно преобразовать к нему, после чего воспользоваться методом ClassType и функцией TypeInfo, которые и обеспечат интроспекцию.
Также отличительным свойством Object Pascal от С++ является то, что объекты по умолчанию располагаются в динамической памяти. Однако можно переопределить виртуальные методы NewInstance и FreeInstance класса TObject. Таким образом, абсолютно любой класс может осуществить «желание» «где хочу — там и буду лежать». Соответственно организуется и «многокучность».
Object Pascal (Delphi) является результатом функционального расширения Turbo Pascal. Delphi оказал огромное влияние на создание концепции языка C# для платформы .NET. Многие его элементы и концептуальные решения вошли в состав С#. Одной из причин называют переход Андерса Хейлсберга, одного из ведущих разработчиков Дельфи, из компании Borland Ltd. в Microsoft Corp.
Ниже приведен перечень свойств, характерных как для C#, так и для Java. Оба эти языка можно рассматривать как попытку усовершенствовать C++, и нужно признать, что в обоих случаях это удалось. Как можно увидеть из приведенного ниже списка, во многом
C# и Java схожи, но было бы неверно отождествлять эти языки.
- Исходный текст программы компилируется в промежуточный код, не зависящий от
языка и платформы; этот код в дальнейшем выполняется в специальной управляемой
среде.
- Автоматический сбор мусора и запрет на использование указателей. В C# допускается ограниченное использование указателей в блоках кода, помечаемых как "ненадежные" (unsafe) .
- Отсутствие заголовочных файлов. Весь код помещается в пакеты (packages) и сборки
(assemblies). Никаких проблем с порядком объявления классов в случае наличия перекрестных ссылок.
-Объекты создаются с помощью ключевого слова new, выделение памяти производится из "кучи" (heap), находящейся в распоряжении среды выполнения.
- Многопоточность поддерживается путем блокирования объектов
- Интерфейсы, множественная реализация интерфейсов классом, однократное наследование базового класса производным.
- Внутренние классы
- Отсутствие концепции наследования классов с заданным уровнем доступа.
- Отсутствие глобальных функций и констант, все элементы должны принадлежать
классам.
- Массивы и строки со встроенной длиной и проверкой границ.
- Не применяются операторы «->» , «::». Во всех случаях используется оператор «.».
- null и boolean / bool являются ключевыми словами.
- Любая величина должна быть проинициализирована до того, как будет использована.
- Нельзя использовать целые числа (integers) для управления операторами if.
- Блоки try могут иметь заключительное предложение finally.
Для эффективной работы в среде CLR и повышения производительности труда программистов в язык C# внесено значительное количество упрощений по сравнению с языком C++. Некоторые из них основаны на следующих особенностях:
-исключение отдельного заголовочного файла и препроцессора;
- устранение проблем с управлением памятью за счет: 1) использования ссылок вместо указателей и 2) сборки мусора во время исполнения.
Вместе с тем синтаксис C# основан на синтаксисе C++ с небольшими изменениям, которые применяются либо для предоставления новых преимуществ, либо для совместимости со средой исполнения CLR.
Свойства (properties): Причина появления свойств в C# заключалась в попытке формализовать на уровне синтаксиса языка концепцию методов get / set, активно используемых программистами, особенно в инструментах класса RAD (Rapid Application Development).
C# предлагает более прозрачный способ реализации свойств, что особенно очевидно для свойств, допускающих чтение и запись. Связь методов get и set в C# ста-
новится врожденной, в то время как в C++ и Java она лишь поддерживается. У такого
подхода есть много преимуществ. Он заставляет программистов мыслить в терминах
свойств, независимо от того доступно ли свойство как для чтения, так и для записи, или
оно предполагает только чтение. Если необходимо изменить название свойства, то дос-
таточно будет сделать это в одном месте (а часто методы get и set оказываются разде-
ленными сотнями строк кода). Комментарии также достаточно ввести в одном месте, так
что они никогда не окажутся рассогласованными.
Можно возразить, что предлагаемый C# синтаксис не дает реальных преимуществ, так как в случае его использования нельзя с уверенностью сказать, с чем мы имеем дело, с полем или свойством. Но практически никогда реальные классы, спроектированные на Java (и естественно на C#), не имеют общедоступных (public) полей. Поля обычно имеют ограниченный уровень доступа (private / protected) и раскрываются только через функции get / set, где C# как раз и предлагает более удобный синтаксис. Кроме того очевидно, что если класс правильно спроектирован, то пользователя должна интересовать только спецификация класса, а отнюдь не его реализация.
Еще один аргумент противников использования свойств - снижение эффективности кода. Однако хороший компилятор может свести реализацию простого метода
получения значения поля (get) к in-line функции, что сделает ее выполнение
столь же быстрым, как и непосредственное считывание значения поля.