Бонусное задание "База+"

  • макс. 4 балла;
  • срок - до 2-го занятия после майских;
  • см. внизу два дополнительных задания.

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

Разработайте класс Expeditor - "смесь" автобуса и грузовика:
  • никакой "своей" функциональности этот класс не добавляет: просто объединяет возможности двух своих "предков";
  • при "приезде" - высаживает на базе всех пассажиров и выгружает весь груз;
  • при "отъезде" - пытается залить полный бак, забрать полный салон пассажиров и полный багажный отсек груза.
  • Обязательно: интерфейс класса Expeditor должен наследовать интерфейсы классов Bus и Truck, интерфейсы классов Bus и Truck должны наследовать интерфейс класса Vehicle.
  • Желательно, чтобы реализации методов тоже наследовались (чтобы избежать дублирования кода). Совет: здесь вам может помочь композиция.

Технические подробности

Это задание - классический пример проблемы ромбовидного наследования.
Так как в Java нет множественного наследования классов, здесь Вам пригодится множественное наследование интерфейсов - в основе иерархии теперь лежит интерфейс IVehicle, а его наследники - IBus и ITruck (букву I писать не обязательно).
Решение этой задачи - не единственно. Рассмотрю любые ваши варианты.

Все изложенные выше "подсказки" и ограничения по реализации можно игнорировать. Главное - сохранить соблюдение принципа подстановки:
Автобус и Грузовик подходят везде, где нужна Машина, а Экспедитор подходит везде, где нужен Автобус или Грузовик (или Машина)

Примеры

ВходВыход 
petrol_on_base = 1000;
people_on_base = 10;
goods_on_base  = 20.000;
vehicles_on_base = 10;

// polymorphism!
IVehicle v = new Expeditor(3, 5, 3.0, 5.0, 200, 300);
v.arrive();

assert(people_on_base == 14);   // 10 + 3 + driver
assert(goods_on_base == 23.0);  // 20 + 3
assert(vehicles_on_base == 11); // 10 + 1

v.leave();

assert(people_on_base == 14 - 6);       // 5+driver left
assert(goods_on_base == 23.0 - 5.0);    // 5 tons left
assert(petrol_on_base == 900);          // minus (300-200)
assert(vehicles_on_base == 10);

System.out.println("OK");
OK

Контрольные вопросы

  • Сколько Вам пришлось написать методов, состоящих из одной строки: return SomeBaseClass.same_func()?
  • Объясните, какое отношение к данной задаче имеют понятия "наследование интерфейса" и "наследование реализации".
  • Что такое instanceof и зачем это нужно?
  • Узнайте, что такое "утиная типизация" и как она помогает (и помогает ли?) решить данную задачу более элегантно. Напишите решение данной задачи на Python'е.*
  • Как будет выглядеть решение этой же задачи на C++?*
*На доп. баллы (сдавать строго в срок!)
Comments