Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:
{
get {return (prof);}
set {prof = value;}
}
Добавим еще в класс Person метод Analysis, анализирующий профессию, организуя традиционный разбор случаев и принимая решение на каждой ветви, в данном примере — выводя соответствующий текст:
public void Analysis
{
switch (prof)
{
case Profession.businessman:
Console.WriteLine ("профессия: бизнесмен");
break;
case Profession.teacher:
Console.WriteLine ("профессия: учитель");
break;
case Profession.engineer:
Console.WriteLine ("профессия: инженер");
break;
default:
Console.WriteLine ("профессия: неизвестна");
break;
}
}
Приведу простой
public void TestProfession
{
Person pers1 = new Person ("Петров");
pers1.Prof = Profession.teacher;
pers1.Analysis ;
}
Результаты работы с объектами перечислений, полученные при вызове тестов TestEnum и TestProfession, показаны на рис. 17.3.
Рис. 17.3. Результаты работы с перечислениями
18. Отношения между классами. Клиенты и наследники
Классы. Отношения между классами. Отношение клиенты — поставщики. Отношение наследования. Единичное наследование. Родители и наследники. Предки и потомки. Что наследуют потомки. Что могут изменить потомки. Одностороннее присваивание. Контроль типов и связывание — статическое и динамическое. Полиморфизм. Проектирование классов. Абстрактные классы. Классы поведения.
Отношения между классами
Каждый класс, как не раз отмечалось, играет две роли: он является модулем — архитектурной единицей, и он имеет содержательный смысл, определяя некоторый тип данных. Но классы программной системы — это ансамбль, в котором классы, играя свои роли, не являются независимыми — все они находятся в определенных отношениях друг с другом. Два основных типа отношений между классами определены в ОО-системах. Первое отношение "клиенты и поставщики", называется часто клиентским отношением или отношением вложенности (встраивания). Второе отношение "родители и наследники" называется отношением наследования.
Определение 1. Классы A и B находятся в отношении ''клиент-поставщик"; если одним из полей класса B является объект класса A. Класс A называется поставщиком класса в, класс B называется клиентом класса A.
Определение 2. Классы A и B находятся в отношении "родитель-наследник", если при объявлении класса B класс A указан в качестве родительского класса. Класс A называется родителем класса B, класс B называется наследником класса A.
Оба отношения — наследования и вложенности — являются транзитивными. Если B — клиент A и C — клиент B, то отсюда следует, что C — клиент A. Если B — наследник A и C — наследник B, то отсюда следует, что C — наследник A.
Определения 1 и 2 задают прямых или непосредственных клиентов и поставщиков, прямых родителей и наследников. Вследствие транзитивности необходимо ввести понятие уровня. Прямые клиенты и поставщики, прямые родители и наследники
Для отношения наследования используется терминология, заимствованная из естественного языка. Прямые классы-наследники часто называются сыновними или дочерними классами. Непрямые родители называются предками, а их непрямые наследники — потомками.
Замечу, что цепочки вложенности и наследования могут быть достаточно длинными. На практике вполне могут встречаться цепочки длины 10. Например, библиотечные классы, составляющие систему Microsoft Office, полностью построены на отношении вложенности. При программной работе с объектами Word можно начать с объекта, задающего приложение Word, и добраться до объекта, задающего отдельный символ в некотором слове некоторого предложения одного из открытых документов Word. Для выбора нужного объекта можно задать такую цепочку: приложение Word — коллекция документов — документ — область документа — коллекция абзацев — абзац — коллекция предложений — предложение — коллекция слов — слово — коллекция символов — символ. В этой цепочке каждому понятию соответствует класс библиотеки Microsoft Office, где каждая пара соседствующих классов связана отношением "поставщик-клиент".
Классы библиотеки FCL связаны как отношением вложенности, так и отношением наследования.
Длинные цепочки наследования достаточно характерны для классов этой библиотеки.
Отношения "является" и "имеет"
При проектировании классов часто возникает вопрос, какое же отношение между классами нужно построить. Рассмотрим совсем простой пример двух классов — Square и Rectangle, описывающих квадраты и прямоугольники. Наверное, понятно, что эти классы следует связать скорее отношением наследования, чем вложенности; менее понятным остается вопрос, а какой из этих двух классов следует сделать родительским. Еще один пример двух классов — Саr и Person, описывающих автомобиль и персону. Какими отношениями с этими классами должен быть связан класс Person_of_Саr, описывающий владельца машины? Может ли он быть наследником обоих классов? Найти правильные ответы на эти вопросы проектирования классов помогает понимание того, что отношение "клиент-поставщик" задает отношение "имеет" ("has"), а отношение наследования задает отношение "является" ("is а"). В случае классов Square и Rectangle понятно, что каждый объект квадрат "является" прямоугольником, поэтому между этими классами имеет место отношение наследования, и родительским классом является класс Rectangle, а класс Square является его потомком.
В случае автомобилей, персон и владельцев авто также понятно, что владелец "имеет" автомобиль и "является" персоной. Поэтому класс Person of Car является клиентом класса Саr и наследником класса Person.
Отношение вложенности
Рассмотрим два класса A и B, связанных отношением вложенности. Оба класса применяются для демонстрации идей и потому устроены просто, не неся особой смысловой нагрузки. Пусть класс-поставщик а уже построен. У класса два поля, конструктор, один статический и один динамический метод. Вот его текст:
public class ClassA
{
public ClassA(string f1, int f2)
{
fieldA1 = f1; fieldA2 = f2;
}
public string fieldA1;
public int fieldA2;
public void MethodA
{
Console.WriteLine ("Это класс A");
Console.WriteLine ("поле1 = {0}, поле2 = {1}",
fieldA1, fieldA2);
}
public static void StatMethodA
{
string s1 = "Статический метод класса A";
string s2 = "Помните: 2*2 = 4";