lec
.pdf{
private double мощность; private double цена;
public double Мощность
{
set { мощность = value; } get { return мощность; }
}
public double Цена
{
set { цена = value; } get { return цена; }
}
}
class Прибор
{
private Корпус кор; private Лампочка лам;
private string состояние; //включено или выключено
//конструктор
public Прибор(Корпус кор, Лампочка лам, string состояние)
{
this.кор = кор; this.лам = лам;
this.состояние = состояние;
}
//свойство
public string Состояние
{
set { Состояние = value; }
}
//вывести данные public void Показать()
{
Console.WriteLine("{0} {1} {2} {3} {4} {5}", состояние, кор.Тип, кор.Цена,
лам.Цена, лам.Мощность);
}
}
В основной программе соберем осветительный прибор из корпуса типа «Тюльпан» ценой 800 рублей и лампочки мощностью 60 Вт, ценой 30 рублей.
class Корпус
{
private string тип; // тип корпуса private double цена;
public string Тип
121
{
set { тип = value; } get { return тип; }
}
public double Цена
{
set { цена = value; } get { return цена; }
}
}
class Лампочка
{
private double мощность; private double цена;
public double Мощность
{
set { мощность = value; } get { return мощность; }
}
public double Цена
{
set { цена = value; } get { return цена; }
}
}
class Прибор
{
private Корпус кор; private Лампочка лам;
private string состояние; //включено или выключено
//конструктор
public Прибор(Корпус кор, Лампочка лам, string состояние)
{
this.кор = кор; this.лам = лам;
this.состояние = состояние;
}
//свойство
public string Состояние
{
set { состояние = value; }
}
//вывести данные public void Показать()
{
122
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", состояние, кор.Тип, кор.Цена,
лам.Цена, лам.Мощность);
}
}
class Program
{
static void Main()
{//1. объявляем ссылки Корпус к; Лампочка л; Прибор п;
//2. создаем объкты к = new Корпус(); к.Тип = "Тюльпан";
к.Цена = 800.0;
л = new Лампочка(); л.Мощность = 60.0;
л.Цена = 30.0;
//3., 4. контейнер
п = new Прибор(к, л, "Включено"); п.Показать();
//меняем лампочку л.Мощность = 200.0; п.Показать();
}
3.Композиция на основе классов
Вэтом случае объект-часть должен создаваться в процессе создания объекта-контейнера.
123
Изменить состояние объекта-части можно только в рамках самого контейнера, извне это сделать нельзя.
Пример Сущности аналогичны базовым. Отличия в предметной области:
осветительный прибор собирается на заводе изготовителе и представляет собой единое целое. Замена частей невозможна.
Отличия в программном коде заключаются в изменении конструктора класса Прибор. В этом конструкторе создаются объекты-части (лампочка и корпус изготавливаются на заводе на основе их технических характеристик, принятых в качестве параметров).
public Прибор(Корпус кор, Лампочка лам, string состояние)
{
this.кор = new Корпус(); this.кор.Тип = кор.Тип; this.кор.Цена = кор.Цена; this.лам = new Лампочка(); this.лам.Цена = лам.Цена;
this.лам.Мощность = лам.Мощность; this.состояние = состояние;
}
Весь остальной код остается неизменным. В обоих случаях будут выведены одни те же характеристики прибора.
//смена эталонной лампочки п = new Прибор(к, л, "Включено");
Если поле, определяющее лампочку в классе Прибор сделать открытым, лампочку можно будет заменить, не создавая нового прибора.
п.лам.Мощность = 200.0;
Но это противоречит описанию предметной области.
4. Композиция на основе структур
Структура – тип данных, который позволяет определять в рамках единого целого поля разных типов и методы их обработки. В этом смысле структура аналогична классу.
Отличия от класса (основные)
1.Структуры относятся к типам значения, т.е. при присваивании одной структуры другой происходит копирование не ссылки, а всех полей структуры.
Копирование выполняется поверхностное (с полей значения снимается копия значений, с полей ссылок снимается копия ссылки).
Таким образом, задача создания осветительного прибора, не допускающего замены корпуса и лампочки, может быть решена с помощью кода абсолютно идентичного коду базового примера пу-
124
тем замены классов Корпус, Лампочка, Прибор, путем замены классов на структуры.
class Æ struct
2.Для структур не поддерживается механизм наследования.
Прочие отличия
1.Конструктор по умолчанию для структур невозможно переопределить, он всегда есть и всегда доступен. Можно добавить конструктор с параметрами.
2.Создания объекта типа stuct не требует операции new. Но в этом случае поля структуры будут неопределенными по значению.
3.При определении структуры запрещена инициализация полей.
125
НАСЛЕДОВАНИЕ
1 Понятие наследования
С точки зрения моделирования предметной области наследование предназначено для описания некоторой сущности (потомка) путем указания отличий от другой сущности (предка).
В ООП наследование рассматривается как отношение между классами, при котором класс-потомок представляет собой разновидность клас- са-предка.
Отношение наследования раскрывает предметную область по типу «общее - специфическое». Представление предметной области в виде наследования представляет собой иерархию, на вершине которой находится класс-предок (базовый класс), а на нижних уровнях – классы-
наследники (наследуемые классы).
Предок может иметь множество наследников. Наследник может иметь не более одного прямого предка. Другими словами, в С# явным образом не поддерживается множественное наследование. Потомок не может унаследовать поля и методы от нескольких прямых предков. Пример наследования приведен на Рис.1.
Автомобиль базовый комплектации
Кузов
Двигатель
Колеса
Фары
Стекла
Автомобиль с про- |
|
Автомобиль с тонированными |
|
Автомобиль без фар |
тив.тум.фарами |
|
стеклами |
|
|
|
|
|
|
|
Противотуманные фары |
|
Стекла |
|
|
|
|
|
|
|
|
|
|
|
|
Кузов |
|
Кузов |
|
Кузов |
Двигатель |
|
Двигатель |
унаследованы |
Двигатель |
Колеса |
унаследованы |
Колеса |
|
Колеса |
Фары |
|
Фары |
|
Фары |
Стекла |
|
Стекла |
|
//отсутствие поля |
//дополнительное поле |
//измененное поле |
Стекла |
||
Противотуманные фары |
Стекла тонированные |
Этот вариант отличия |
||
|
|
|
|
не возможен |
Рис.1
Специфические черты классу-потомку могут быть приданы двумя способами:
- Дополнение унаследованных от предка полей и методов новыми полями и методами. В результате потомок становится сложнее по структуре и поведению.
126
- Изменение унаследованных от предка полей и методов. В результате потомок не становится сложнее, меняется лишь способ реализации полей и методов, то есть имеет место отношение: то же самое, но сделано по-другому.
Механизм реализации:
-При определении класса-потомка указывается базовый класс: class ИмяКласса: ИмяБазовогоКласса;
-В классе определяются дополнительные поля и методы или переопределяются поля и методы базового класса.
С точки зрения технологии программирования наследование позволяет решить проблемы:
•Повторное использование кода (создание новых классов на основе существующих)
•Модификация существующего кода (изменение в базовом классе немедленно приводит к изменению в классах-потомках)
2.Наследование как средство усложнения базового класса
Реализуется путем определения в классе-потомке дополнительных
полей, методов и свойств. Класс-потомок будет иметь:
•Унаследованные поля, методы и свойства
•Дополнительные поля, методы и свойства
Конструкторы не наследуются, поэтому класс-потомок должен иметь собственный конструктор. При создании объекта класса-потомка конструкторы должны вызываться, начиная с базового класса. В начале инициализируются унаследованные поля, потом – специфические поля, как показано на Рис.2.
Базовый Потомок
Класс 1 |
|
Класс 2 |
Создать объект: |
|
|
|
Конструктор базового класса |
|
|
|
|
|
|
|
Конструктор потомка |
|
|
|
|
Рис.2 Указанная очередность вызовов реализуется одним из способов:
1.Конструктор потомка не имеет вызова конструктора-предка. Автоматически вызывается конструктор предка без параметров.
2.Конструктор потомка явно вызывает конструктор предка.
Рис.3
127
Пример: определить базовый класс «Человек». Человек характеризуется фамилией и умением сообщать свою фамилию. Потомками класса «Человек» являются:
-класс «Владелец», дополнительно характеризующийся номером автомобиля и умением сообщать его
-класс “Служащий”, дополнительно характеризующийся названием фирмы и умением сообщать его.
-класс “Студент”, дополнительно характеризующийся названием ВУЗа
class Человек
{
protected string фам; public Человек(string фам)
{
this.фам = фам;
}
public void Показать()
{
Console.WriteLine("Я - человек: " + фам);
}
}
class Студент:Человек
{
private string вуз;
public Студент(string фам, string вуз):base(фам)
{
this.вуз = вуз;
}
}
class Владелец: Человек
{
private string ном;
public Владелец(string фам, string ном): base(фам)
{
this.ном = ном;
}
public void Инфо()
{
Console.WriteLine("Я - владелец: "+фам+" --> " + ном);
}
}
class Служащий: Человек
{
private string фирма;
public Служащий(string фам, string фирма): base(фам)
{
this.фирма = фирма;
}
128
public void Инфо()
{
Console.WriteLine("Я - служащий: "+фам + "____" + фирма);
}
}
class Program
{
static void Main(string[] args)
{
Студент ст = new Студент("Иванов","ВШЭ");
Владелец вл = new Владелец("Петров", "A777AA-99RUS"); Служащий сл = new Служащий("Сидоров", "Рога и копыта");
ст.Показать(); //Унаследованный метод //Я - человек: Иванов
вл.Показать(); //Унаследованный метод //Я - человек: Петров
сл.Инфо(); // Дополнительно определенный метод //Я - служащий: Сидоров ______ Рога и копыта
вл.Инфо(); //Дополнительно определенный метод
//Я - владелец: Петров --> A777AA-99RUS
}
}
Для работы с объектом-потомком могут быть использованы ссылки типа Предок и Потомок. Ссылке базового класса можно присвоить ссылку на класс-потомок. Ссылки типа Предок можно использовать только для доступа к унаследованным полям, методам и свойствам (предок ничего не знает о том, что «привнесли» потомки).
Рис.4
129
class Человек
{
protected string фам; public Человек(string фам)
{
this.фам = фам;
}
public void Показать()
{
Console.WriteLine("Я - человек: " + фам);
}
}
class Владелец: Человек
{
private string ном;
public Владелец(string фам, string ном): base(фам)
{
this.ном = ном;
}
public void Инфо()
{
Console.WriteLine("Я - владелец: "+фам+" --> " + ном);
}
}
class Program
{
static void Main(string[] args)
{
Человек ч;
Владелец вл = new Владелец("Петров", "A777AA-99RUS");
ч = вл; ч.Показать(); //Унаследованный метод //Я - человек: Петров
вл.Показать(); //Унаследованный метод //Я - человек: Петров
ч.Инфо(); |
//Ошибка |
|
вл.Инфо(); |
//Дополнительно определенный метод |
|
//Я - владелец: Петров |
--> A777AA-99RUS |
}
}
Возможность усложнять базовый класс может рассматриваться как альтернатива агрегации. При этом необходимо помнить, что механизмы наследования и агрегации реализуются по-разному.
Наследование – это аналог производства изделия «с нуля». Базовый чертеж (класс) дополняется и полученный чертеж изделия (класснаследник) используется для изготовления изделия (объекта). На этапе
130