учебники, программирование, основы, введение в,

 

Концепция наследования и ее реализация в языке C#

Формализуем понятие наследования и обсудим его значение для объектно-ориентированного подхода к программированию. Напомним, что эволюция теоретических основ наследования была рассмотрена во вступительной лекции.
Под наследованием в дальнейшем будем понимать свойство производного объекта сохранять поведение родительского объекта. Под поведением будем иметь в виду для математического объекта его атрибуты и операции над ним, а для языкового объекта ООП – поля и методы.
Таким образом, применительно к языку программирования концепция наследования означает, что свойства и методы базового класса равно применимы к производным от него классам. Заметим, что дочерний объект не обязательно наследует все без исключения атрибуты и операции родительского, а лишь некоторые из них. Такой подход характерен как для классов объектов в целом, так и для отдельных их конкретизаций, или, иначе, экземпляров.
Теоретическая концепция наследования удовлетворительно моделируется посредством отношения (или, точнее, иерархии) частичного порядка. Существует целый ряд формализаций наследования, но наиболее адекватными и концептуально ясными являются графические модели. Среди них следует выделить уже упомянутые ранее подходы: фреймовую нотацию Руссопулоса и диаграммы Хассе.
Отношение частичного порядка обладает следующими теоретически интересными и практически полезными свойствами.
Во-первых, оно является рефлексивным, т.е. любой объект языка программирования или формальной модели предметной области находится в отношении частичного порядка с самим собой. Формальная запись свойства рефлексивности для отношения частичного порядка ISA выглядит следующим образом:
 a: a ISA a.
Другой важной особенностью отношения частичного порядка является транзитивность. Суть транзитивности состоит в том, что если существует цепочка из (трех) объектов, связанных отношением частичного порядка, то первый и последний элементы этой цепочки можно связать тем же отношением. Это свойство гарантирует построение на множестве графа отношения частичного порядка в виде «решетки». Формальная запись свойства транзитивности для отношения частичного порядка выглядит следующим образом:
 a,b,c: a ISA b, b ISA c  a ISA c.
Наконец, еще одним фундаментальным свойством отношения частичного порядка как модели наследования является антисимметричность. Это свойство разрешает наследование только в одном направлении (и запрещает его в противоположном). Формальная запись свойства антисимметричности для отношения частичного порядка выглядит следующим образом:
 a,b : a ISA b  NOT (b ISA a).
По завершении исследования свойств отношения частичного порядка, перейдем к рассмотрению формализаций, моделирующих наследование. Проиллюстрируем графическую интерпретацию отношения частичного порядка на примере фреймовой нотации Руссопулоса. Рассмотрим следующий фрейм, который связывает отношением частичного порядка понятия «сущность» (THING), «юридическое лицо» (LEGAL.PERSON), «учреждение» (INSTITUTION), «работодатель» (EMPLOYER), «кадровое агентство» (RECRUITER), «физический объект» (PHYSICAL.OBJECT), «одушевленный объект» (ANIMATE.OBJECT), «человек» (PERSON), «мужчина» (MALE.PERSON) и «женщина» (FEMALE.PERSON).
Как видно из структуры фрейма, понятия (или, точнее, концепты) изображены в овалах. Направленные ISA-дуги соединяют понятия, образуя иерархию с направлением в сторону увеличения уровня общности (абстракции), например, от понятия «мужчина» к понятию «сущность». Рефлексивные и транзитивные дуги опущены для удобства восприятия; их без труда можно восстановить. Ориентированность дуг характеризует антисимметричность отношения частичного порядка: любая из дуг может иметь только одну стрелку со стороны увеличения уровня абстракции.
Другой продуктивной формализацией, моделирующей, в частности, наследование, является диаграмма Хассе. Проиллюстрируем использование диаграмм Хассе для графической интерпретации отношения между элементами класса или домена
Диаграмма Хассе состоит из точек, которые представляют элементы множества (точнее, домена или класса), а также из соединяющих их линий, которые представляют собой отношения между элементами класса или домена (в данном случае интерпретируется отношение частичного порядка).
Данный пример иллюстрирует отношение IS IN («является подмножеством») между множествами {}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3} и {1,2,3}.
Заметим, что в случае графической интерпретации отношения частичного порядка с помощью диаграммы Хассе свойство антисимметричности рассматриваемого отношения было бы отображено в явном виде.

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

class A {
// базовый класс 
   int a;
   public A() {...}
   public void F() {...}
}
 
class B : A {  
// подкласс (наследует свойства класса A, 
// расширяет класс A)
   int b;
   public B() {...}
   public void G() {...}
}

Применительно к языку программирования C# наследование есть отношение между классами. Данный пример содержит описание более общего (находящегося выше по ISA-иерархии) класса A и его подкласса – класса B. Заметим, что находящийся выше по ISA-иерархии класс принято называть базовым, а находящийся ниже – производным (или подклассом).
Подкласс B наследует свойства класса A, и, кроме того, возможно, расширяет его новыми (по сравнению с классом A) свойствами.
Приведенный фрагмент программы на языке C# иллюстрирует простейший случай наследования, а именно, единичное наследование.
Рассмотрим подробнее, каким образом производится реализация механизма наследования.
Производный класс B наследует свойство a и метод F() базового класса A. Кроме того, к свойствам производного класса B добавляется новое по сравнению с базовым классом A свойство b, а к методам – новый по сравнению с базовым классом A метод G().
Заметим, что операторы конкретизации элементов базовых классов (которые в языке C# называют конструкторами) не наследуются производными классами. Отметим также, что некоторые из наследуемых методов могут игнорироваться. В ходе единичного наследования производный подкласс может наследовать свойства единственного базового класса. Множественное наследование, демонстрирующее гибкость механизмов наследования в языке C#, реализуется на основе интерфейсов. Хотя производный класс в языке программирования C# может наследовать свойства базового класса, он не может наследовать свойств структуры. Реализация механизма наследования (в том числе множественного) для структур в языке программирования C# осуществляется (как и в случае с классами) посредством интерфейсов.
В случае неявного задания базового класса производный класс наследует свойства наиболее общего класса Microsoft .NET, известного как объект (object) и аналогичного концепту THING («сущность») в рассмотренном ранее примере фреймовой нотации.
Для иллюстрации множественного наследования приведем фрагмент программы на языке C#, содержащей описание интерфейса:

public interface IList : 
   ICollection, IEnumerable    
{
   int Add (object value);     
   // методы 
   bool Contains (object value);
   bool IsReadOnly {
      get;
   }
   // свойство 
   object this [int index]{
      get;
      set;
   }
   // индексатор
}

Из приведенного примера видно, что фрагмент программы на языке C# представляет собой описание общедоступного интерфейса IList, наследующего в иерархии элементы интерфейсов ICollection и IEnumerable, а также содержащего методы Add и Contains, свойство IsReadOnly и объект-индексатор.


После визуального знакомства с кодом на языке программирования C#, описывающим интерфейс, приведем более общее словесное определение этого механизма, имеющего принципиальное значение.
Интерфейсом называется чисто абстрактный класс (с поддержкой полиморфизма), содержащий только описания без реализации.
Концепция множественного наследования предполагает возможность наследования одним концептом языка свойств сразу нескольких языковых концептов. При этом в языке программирования C# принципиально допустимо множественное наследование, но область действия его ограничена интерфейсами. Множественное наследование классов в языке программирования C# недопустимо, однако неявно реализуемо посредством интерфейсов. Так, классы и структуры языка программирования C# могут реализовывать множественные интерфейсы.
Интерфейсы могут содержать методы, свойства, индексаторы и события. Однако интерфейсы не могут содержать полей, констант, конструкторов, деструкторов, операторов, а также вложенных типов.
Элементы интерфейса неявно являются виртуальными (т.е. общедоступными и абстрактными) объектами и описываются в языке C# как public abstract (или virtual).
Интерфейсы, будучи принципиально полиморфными (т.е. динамически означиваемыми) объектами, не могут содержать статических элементов.
Наконец, свойства одного интерфейса могут быть расширены посредством другого интерфейса.
Рассмотрим более подробно важнейшие свойства интерфейсов как механизма реализации концепции множественного наследования в языке программирования C#.
Как уже отмечалось, концепция множественного наследования в языке программирования C# неприменима в явной форме для классов. В случае классов существует возможность только единичного наследования, т.е. производный класс может наследовать свойства единственного базового класса. Механизм интерфейсов, таким образом, представляет собой неявную возможность реализации концепции множественного наследования для языка программирования C#, поскольку для классов в языке допустима реализация множественных интерфейсов.
В отношении наследования структур в языке программирования C# наблюдается определенное сходство с классами. В частности, несмотря на то обстоятельство, что структуры не имеют возможности наследовать свойства типов, для них, как и для классов, допустима реализация множественных интерфейсов.
При этом произвольный элемент интерфейса, будь то метод, свойство или индексатор, должен непременно быть либо реализован непосредственно в базовом классе, либо унаследован от него.
Кроме того, заметим, что реализованные в языке программирования C# методы интерфейса могут быть описаны либо как виртуальные (virtual), либо как абстрактные (abstract). Таким образом, интерфейс может быть реализован посредством абстрактного класса. В то же время не допускается реализация замещенных интерфейсов по аналогии с замещенными в производных классах методами, которые описываются посредством ключевого слова override языка программирования C#.
Концепция наследования, рассмотренная нами применительно к объектно-ориентированному подходу к программированию, вполне может быть распространена и на случай систем и сред, поддерживающих проектирование и реализацию программного обеспечения.
В этой связи не является исключением и среда интегрированной разработки приложений Microsoft .NET, классы которой не имеют существенных различий с классами языка программирования C#.
Как видно из схемы, описывающей основные пространства имен Microsoft .NET Framework, организация их является вполне иерархической и реализует классическую схему единичного наследования.
Наиболее общим концептом иерархии является пространство имен System, характеризующее конфигурацию среды Microsoft .NET Framework и содержащее, в частности, параметры среды выполнения приложений, удаленной обработки данных, процессов, безопасности, ввода-вывода, системной конфигурации и др.
Среди подпространств пространства имен System можно выделить такие пространства имен, как System.Web, System.Windows.Forms, System.Data, System.Drawing и System.Xml, которые описывают такие характеристики среды Microsoft .NET Framework, как конфигурации веб-сервисов, формы ввода-вывода данных, форматы представления данных, графических подсистем и т.д.
Данная схема иллюстрирует перечень классов Common Type System среды проектирования и реализации программного обеспечения Microsoft .NET применительно к языку программирования C#.
В частности, все многообразие типов можно разделить на предопределенные (заранее заданные системой программирования) и определенные пользователем (user defined) типы.
К последним относятся перечисления, массивы, классы, интерфейсы и делегаты (указатели на функцию).
Предопределенные типы делятся на ссылочные типы (объекты и символьные строки) и типы-значения (встроенные – короткие и длинные целые со знаком и без знака, а также числа с плавающей точкой – с одинарной и двойной точностью).
Напомним, что все без исключения типы языков программирования SML и C# однозначно отображаются в систему типизации Microsoft .NET, верхним иерархическим элементом которой является пространство имен System.
Подводя итоги обсуждения наследования, одной из основополагающих концепций объектно-ориентированного подхода к программированию, кратко резюмируем положительные аспекты явления и вытекающие из них практические возможности.
Прежде всего, концепция наследования устраняет необходимость многократного явного указания свойств и методов для производных объектов. Одного взгляда на схему пространств имен Microsoft .NET Framework достаточно, чтобы понять значимость этого свойства. Заметим, что на схеме показана лишь часть верхних «этажей» многоуровневой иерархии.
Кроме того, следует отметить, что наследование открывает возможности для гибкого определения уровня абстракции предметной области. Можно оперировать единственным, достаточно абстрактным, концептом System (или THING на), и, спускаясь по ISA-иерархии, обращаться к терминам все более конкретных концептов и сущностей (или, в терминологии языка программирования C#, классов и объектов).
Таким образом, концепция наследования предоставляет возможность моделирования сколь угодно сложной предметной области посредством ISA-иерархии концептов (или классов языка программирования C#), моделирующих объекты реального мира.
Итак, наследование прозрачный и унифицированный подход к построению классов (которые в терминологии языка программирования C# принято называть производными) по заданной совокупности свойств и методов так называемых базовых классов.
Заметим, что в языке программирования C# допустимо наследование свойств и методов как от единственного класса (единичное), так и от нескольких классов (множественное). Последний вид наследования реализуется посредством механизма интерфейсов.
Для моделирования наследования можно воспользоваться фреймами Н. Руссопулоса и диаграммами Х. Хассе.

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика