Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С# и объектно-ориентированное программирование.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
1.3 Mб
Скачать
    1. Ключевое слово as

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

// Нет! Приводить o к типу Hexagon нельзя, хотя код скомпилируете*!

object o = new Manager("Frank Zappa", 9, 40000, “11-11-1111", 5) ;

Hexagon hex = (Hexagon)o;

компилируется нормально, но вызывает ошибку времени выполнения, или, более формально — исключение времени выполнения. Далее будут рассматриваться подробности структурированной обработки исключений, а пока следует лишь отметить, что при выполнении явного приведения можно перехватывать возможные ошибки приведения, применяя ключевые слова try и catch:

// Перехват возможной ошибки приведения.

object o = new Manager("Frank Zappa", 9, 40000, “11-11-1111", 5) ;

try

{

Hexagon hex = (Hexagon)o;

}

catch (InvalidCastException ex)

{

Console.WriteLine(ex.Message);

}

Хотя это хороший пример защитного (defensive) программирования, С# предоставляет ключевое слово as для быстрого определения совместимости одного типа с другим во время выполнения. С помощью ключевого слова as можно определить совместимость, проверив возвращенное значение на равенство null. Взгляните на следующий код:

// Использование as для проверки совместимости

object o = new Manager("Frank Zappa", 9, 40000, “11-11-1111", 5) ;

Hexagon hex2 = o as Hexagon;

if (hex2 == null)

Console.WriteLine("Sorry, o is not a Hexagon...");

    1. Ключевое слово is

Учитывая, что метод GivePromotion() был спроектирован для приема любого возможного типа, производного от Employee, может возникнуть вопрос — как этот метод может определить, какой именно производный тип был ему передан? И, кстати, если входной параметр имеет тип Employee, как получить доступ к специализированным членам типов SalesPerson и Manager?

В дополнение к ключевому слову as, в С# предлагается ключевое слово is, которое позволяет определить совместимость двух типов. В отличие от ключевого слова as, если типы не совместимы, ключевое слово is возвращает false, а не null-ссылку. Рассмотрим следующую реализацию метода GivePromotion():

(этот код вставляем в проект EmployeeExample, класс Program)

Задание!!!: протестировать, исправить возможные ошибки

Здесь во время выполнения производится проверка, на что именно в памяти указывает ссылка типа базового класса. Определив, что принят SalesPerson или Manager, можно применить явное приведение и получить доступ к специализированным членам класса. Также обратите внимание, что окружать операции приведения конструкцией try/catch не обязательно! поскольку внутри контекста if, выполнившего проверку условия, уже известно, что приведение безопасно.

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

В мире ООП помимо наследования существует еще одна форма повторного использования кода. Эта форма называется включением-делегированием (или отношением «иметь» - has a). При ее использовании один класс включает в свой состав другой и открывает внешнему миру часть возможностей этого внутреннего класса.

Например если мы создаем программную модель автомобиля, то может понадобиться включить внутрь объекта «автомобиль» объект «радио» с помощью отношения «иметь». Это вполне разумный подход, поскольку вряд ли возможно произвести как радио от авто, так и авто от радио, используя отношение наследования. Вместо наследования мы создаем два независимых класса, работающих совместно, где внешний (контейнерный) класс создает внутренний класс и открывает внешнему миру его возможности.

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

Пример 3.

Программная модель автомобиля.

Для начала создадим новое консольное приложение С# по имени CarExample.

(этот код вставляем в проект CarExample, namespace Car)

Задание!!!: протестировать, исправить возможные ошибки

В классе Car (показанном ниже), сделаем так, чтобы в случае превышения объектом Саг предопределенной максимальной скорости (отражаемой с помощью константы экземпляра MaxSpeed) двигатель выходил из строя, приводя его в нерабочее состояние (отражаемое приватной переменной экземпляра bool по имени dead). Кроме того, включим в Саг свойства для представления текущей скорости и указанного пользователем "дружественного названия" автомобиля и различные конструкторы для установки состояния нового объекта Саг.

(этот код вставляем в проект CarExample, namespace Car)

Задание!!!: протестировать, исправить возможные ошибки

Сейчас в нашем распоряжении есть два независимых класса – Radio и Car. Понятно, что эти два класса должны взаимодействовать друг с другом и эти отношения надо зафиксировать некоторым образом. Зафиксируем эти отношения с помощью включения-делегирования: пусть машина включает в себя радио и передает этому классу необходимые команды. Помещение приемника внутрь авто влечет за собой внесение в определение класса Car следующих изменений:

(этот код вставляем в проект CarExample, класс Car)

Задание!!!: протестировать, исправить возможные ошибки

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

(этот код вставляем в проект CarExample, в конструкторы класса Car)

Задание!!!: протестировать, исправить возможные ошибки

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

Например, в класс Car добавляем такой метод:

(этот код вставляем в проект CarExample, в класс Car)

Задание!!!: протестировать, исправить возможные ошибки

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

(этот код вставляем в проект CarExample, в класс Program)

Задание!!!: протестировать, исправить возможные ошибки