Введение в теорию программирования. Объектно-ориентированный подход

         

Теория типов и типизация в .NET


Обсудим основы дисциплины типов в рамках .NET. Напомним, что история развития математических формализаций для типовых теорий изложена во вступительной лекции, а основа теории типов - в лекции 6.

Обобщим те преимущества, которые отличают языки программирования и формальные теории с типами.

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

Введение типизации облегчает и упорядочивает не только восприятие, но и управление предметной областью. Манипулирование типизированными элементами носит более целенаправленный характер, причем появляется возможность обрабатывать разнородные сущности предметной области различным образом, а однородные (или, точнее, однотипные) - единообразно.

Перейдем к языкам программирования и практике проектирования и реализации программных систем. В случае построения языка программирования по принципу строгой типизации несоответствия типов фиксируются до начала этапа выполнения программы (на этапе контроля соответствия типов в ходе трансляции), что гарантирует отсутствие семантических (смысловых) и логических ошибок и безопасность программного кода.

Напомним классификацию систем типизации в языках программирования.

Исторически наиболее распространенной для языков программирования является строгая типизация. При таком формировании системы типов в языке в любой момент существования любого языкового объекта существует однозначное соответствие между объектом и его типом. Другими словами, можно запрограммировать функцию, определяющую тип объекта, подобную ранее рассмотренной нами функции typeof языка программирования C#. Строго типизированными являются классические императивные языки программирования Pascal, FORTRAN, PL/I и др. Отметим, что классический вариант языка программирования C не является строго типизированным.

Сильная типизация необходима для обеспечения корректности связывания переменных со значениями до выполнения программы.
табл. 18.1):

При этом типы- значения распадаются на следующие подтипы:



  • элементарные (в частности, целочисленные и вещественные):

    int i; float x;



  • перечислимые (в частности, моделирующие переключатели):

    enum State {Off, On}



  • структурные (в частности, моделирующие точки на плоскости):

    struct Point {int x,y;}



В свою очередь, ссылочные типы подразделяются на следующие подтипы:

  • корневой подтип (указатели на произвольные объекты в иерархии типов в Common Type System):

    object





  • строковые (указатели на строки символов):

    string



  • классы (указатели на объекты типа class):

    class Foo: Bar, IFoo {...}



  • интерфейсы (указатели на объекты типа interface):

    interface IFoo: IBar {...}



  • массивы (в частности, указатели на строки из 10 символов):

    string[] a = new string[10];



  • делегаты (усовершенствованные указатели на функцию):

    delegate void Empty();




Рис. 18.2.  Иерархия типов языка C# (фрагмент).

Многообразие типов можно разделить на предопределенные (заранее заданные системой программирования) и определенные пользователем (user defined), см. рис. 18.2.

К последним относятся перечисления, массивы, классы, интерфейсы и делегаты (указатели на функцию).

Предопределенные типы делятся на ссылочные типы (объекты и символьные строки) и типы-значения (встроенные - короткие и длинные целые со знаком и без знака, а также числа с плавающей точкой - с одинарной и двойной точностью).

Как уже отмечалось, над элементами типов могут осуществляться преобразования из одного типа данных в другой (например, из строки в число или наоборот). При этом такие преобразования могут инициироваться как программистом (т.е. происходить явно), так и системой программирования (т.е. происходить неявным образом).

Неявные преобразования инициируются Common Type System и производятся автоматически. При этом результат неявного преобразования всегда успешен и не приводит к потере точности.

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

Приведем ряд примеров преобразований типов на языке программирования C#:

int x = 25; long y = x; // неявное short z = (short) x; // явное double d = 3.141592536; float f = (float) d; // явное long l = (long) d; // явное

Заметим, что система Common Type System среды Microsoft .NET обеспечивает безопасную типизацию, т.е. гарантирует отсутствие побочных эффектов (переполнение оперативной памяти компьютера, некорректное преобразование типов и т.д.). Заметим также, что как явные, так и неявные преобразования типов могут инициироваться пользователем.



Значение механизма пространств имен состоит в том, что появляется возможность логической структуризации системы типизации Common Type System в среде разработки приложений Microsoft .NET.

Описания пространств имен по аналогии с описаниями типов данных размещаются в файлах.

Перечислим основные свойства, которыми характеризуются пространства имен в среде Microsoft .NET:



  1. пространства имен могут объединять различные сборки;


  2. пространства имен могут быть вложенными друг в друга;
  3. между пространствами имен и файлами не существует однозначного соответствия (т.е. отображения, переводящего название пространства имен в имя файла);
  4. полное имя типа должно содержать все необходимые пространства имен.


Для иллюстрации применения механизма пространств имен в среде программирования Microsoft .NET приведем развернутый пример описания пространств имен на языке программирования C#:

namespace N1{ // N1 class C1{ // N1.C1 class C2{ // N1.C1.C2 } } namespace N2{ //N1.N2 class C2{ // N1.N2.C2 } } }

Рассмотренный пример содержит описания пространств двух имен: пространства N1 с описанием классов C1 и C2 и пространства N2 с описанием класса C2.

Заметим, что в комментариях к каждой строке программы на языке C# приведены полные наименования пространств имен. Так, для обращения к классу C2, описанному в пространстве имен N1, нужно использовать полное имя N1.C1.C2, а для обращения к классу C2, описанному в пространстве имен N2 - полное имя N1.N2.C2.

Таким образом, при адекватном употреблении полных квалификационных наименований пространств имен удается избежать коллизии обозначений типов.

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

Оказывается, что непременное использование полных имен типов в среде программирования Microsoft .NET является избыточным требованием.

Для экономии трудозатрат и во избежание коллизий обозначений при разработке крупных программных систем в языке программирования C# предусмотрен оператор using, к рассмотрению которого мы и переходим.


Содержание раздела