Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 2. Наследование.doc
Скачиваний:
5
Добавлен:
15.11.2019
Размер:
273.92 Кб
Скачать

Применение модели включения-делегирования

Как уже говорилось, в объектно-ориентированных языках программирования исполъзуются две главные разновидности наследования. Первая из них называется классическим наследованием (моделью «быть» — is-a), и эта модель была рассмотрена в предыдущем разделе. Вторая разновидность — это модель включения-делегирования (модель «иметь» — has-a), и именно ей посвящен настоящий раздел.

Для начала нам потребуется простой класс, представляющий автомобильный радиоприемник:

// Этот класс будет внутренним, включенным в другой класс - Саг

pubic class Radio

{

public Radio( ){}

public void TurnOn(bool on)

{

if(on)

Console.WriteLine(“Jamming. ");

else

Console.WriteLine(“Quiet time . ");

}

}

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

//Этот класс будет выступать в роли внешнего класса, класса-контейнера для Radio

public class Car

{

private int currSpeed;

private int maxSpeed;

private string petName;

bool dead; // Жива ли машина или уже нет

public Саг()

{

maxSpeed = 100;

dead = false;

}

public Car(string name, int max, int curr)

{

currSpeed = curr;

maxSpeed = max;

petName = name;

dead = false;

}

public void SpeedUp (int delta)

{ …… }

Сейчас в нашем распоряжении есть два независимых класса — Radio для авто мобильного радиоприемника и Саг для самого автомобиля Понятно, что эти два класса должны взаимодействовать друг с другом и эти отношения желательно как то зафиксировать Однако вряд ли нам удаст ся применить в этом случае класси ческое наследование трудно производить машину от радиоприемника ичи радио приемник от машины В этой ситуации, конечно больше подойдет отношение включения-делегирования пусть машина включает в себя радио и передает этому классу необходимые команды В терминологии объектно ориентированного про граммирования контейнерный класс (в нашем случае Саг) называется родитель ским (parent), а внутренний класс, который помещен внутрь контейнерного (это конечно Radio), называется дочерним (child).

Помещение радиоприемника внутрь автомобиля влечет за собой внесение в опре деление класса Саг следующих изменений:

// Автомобиль «имеет» (has а) радио

public class Car

{

. . . . . .

// Внутреннее радио

private Radio theMusicBox;

}

Обратите внимание, что внутренний класс Radi о был объявлен как private С точки зрения инкапсуляции мы делаем все правильно Однако при этом неизбежно возникает вопрос: а как нам включить радио? Переводя на язык программировая — а как внешний мир будет взаимодействовать с внутренним классом? Понятнo, что ответственность за создание объекта внутреннего класса несет внешний контейнерный класс. В принципе код для создания объектов внутреннего класса можно помещать куда угодно, но обычно он помещается среди конструкторов контейнерного класса:

// За создание объектов внутренних классов ответственны контейнерные классы

public class Car

{

. . .

// Встроенное радио

private Radio theMusicBox;

public Car( )

{

maxSpeed = 100;

dead = false;

// Объект внешнего класса создаст необходимые объекты

//внутреннего класса при собственном создании

theMusicBox = new Radio( ); // Если мы этого не сделаем theMusicBox

// начнет свою жизнь с нулевой ссылки

}

public Car(string name, int max, int curr)

{

currSpeed = curr;

maxSpeed = max;

petName = name;

dead = fales;

theMusicBox = new RadioO;

}

. . . .

}

Произвести инициализацию средствами С# можно и так:

// Автомобиль «имеет» (has-a) радио

public class Car

{

. . . .

// Встроенное радио

private Radio theMusicBox = new Radio( );

. . . .

}

Таким образом, радиоприемник внутри автомобиля у нас теперь создается есте с автомобилем. Однако вопрос о том, как именно можно включить этот раприемник, остался нерешенным. Ответ на него выглядит так:- для того чтобы воспользоваться возможностями внутреннего класса, необходимо делегирование (delegation). Делегирование заключается в простом добавлении во внешний контейнерный класс методов для обращения ко внутреннему классу, шример:

// Во внешний класс добавляются дополнительные открытые методы и другие члены

// которые обеспечивают доступ к внутреннему классу

public class Car

{

. . . .

public void CrankTunes(bool state)

{

// Передаем (делегируем) запрос внутреннему объекту

theMusicBox.TurnOn(state);

}

}

В приведенном ниже коде обратите внимание на то, что пользователь косвенно обращается к скрытому внутреннему объекту, даже не подозревая о том, что в недрах объекта Саг существует закрытый (определенный как private) объект Radio:

// Выводим автомобиль на пробную поездку

public class CarApp

{

public static int Main(string[ ] args)

{

// Создаем автомобиль (который, в свою очередь, создаст радио)

Саг c1;

c1 = new Car( “SlugBug”, 100, 10);

// Включаем радио (запрос будет передан внутреннему объекту)

c1.CrankTunes(true);

// Ускоряемся

for(int i=0; i < 10; i++)

c1.SpeedUp(20);

// Выключаем радио (запрос будет вновь передан внутреннему объекту

c1.CrankTunes(false);

return 0;

}

}