C# Множественное наследование
Такая задача: Есть класс автомобиль, у него есть много полей ( координата, скорость, длина авто и т.д.)
Класс легковой автомобиль - наследник автомобиля: в конструкторе легкового автомобиля сложной формулой и некоторыми коснтантами задается длина авто, не превышающая некоторое значение
Класс Грузовой втомобиль - тоже наследник автомобился, но у него длина задается по другому: не менее некоторого значения.
Теперь дальше. Машины также бывают с остановками. Например такси (наследник легкового авто) и автобус (наследник грузового авто). Так вот у машин с остановками очень много общего: поле "массив остановок" и сложный метод Move(), который переопределяет базовый метод Move() для класса "автомобиль"
(может быть важное замечание, метод move обязательно использует поля класса Автомобиль)
"Если бы"
Если бы в C# можно было бы делать множественное наследование, я бы просто написал, что такси - потомок класса Легковой автомобиль, и автомобиль состановками; а автобус - соответственно грузовой автомобиль и с остановками.
Вопрос: как реализовать данную структуру. Очень желательно без дублирования кода
П.С. Надеюсь способ не сильно геморный, т.к. на этом факультете сильно умничать, показывая высший пилотаж ООП - не всегда полезно
СПАСИБО! ! !
Остановки - если уж на то пошло - это свойства класса Маршрут - и никакого отношения наследования к автомобилю иметь не должен. Автомобиль может иметь привязку к координатам маршрута (для простоты это может быть функция возвращающая некую широту-долготу, хотя лично бы я вынес этот функционал за пределы класса авто) а стоянки-остановки - это композиты класса Маршрут.
Так же неправильно определять класс авто на основании
разница между грузовым и легковым авто - в первую очередь в грузоподъемности. А зато, некоторые лимузины в твой класс автомобилей легко не попадут. Хотя машины легковые. Но это не существенные мелочи.
совершенно не логично. А как в таком случае фиксировать остановку из-за поломки? Аварии? :)
Остановки - это свойства маршрута. Это первое. Второе - метод move судя по всему просто не грамотно спроектирован. Он должен всего навсего возвращать либо скорость конкретного объекта автомобиля, либо 1-0 (движется-не движется). Но здесь опять же возникают некоторые моменты - скорость правильно считать относительно чего-то, с другой стороны - автомобиль оборудован спидометром, который отображает скорость конкретного авто. Будет ли правильным возвращать это значение через move() - я честно говоря не знаю, зависит от задачи. Но как простое решение - это годиться. Если же рассматривать
move(Авто *, НаборТочекМаршрута *)
как перемещение от точки до точки для конкретного объекта, наследующего от Авто - то этот метод должен принадлежать к классу, допустим, Маршрута. Включать его в класс Авто - ошибка.
Остановки - это свойства маршрута. Это первое. к классу, допустим, Маршрута. Включать его в класс Авто - ошибка.
Создавать лишний класс - это ошибка.
Маршрут - а если автомобиль не доехал, что делать с незавершенным маршрутом?
Я подобную систему разрабатывал - движение ящиков по автоматическим транспортерам. Тоже вот не смог доказать, что не должно быть у ящика заранее определенного маршрута, а только коллекция пунктов назначения - которые он должен обьехать по произвольному маршруту, по принципу TCP/IP пакета,
а направлять его на каждый участок пути будет "шахматная доска" - пункт остановки, в полной аналогии с раутером. И это дало бы возможность направить ящик по свободному пути, и продолжить движение без дополнительных действий после аварийной остановки системы.
Поехал ящик, у него список поворотов, а связь с контроллером взяла, и пропала. ящик стоит посередине, и не едет - чисто практический опыт - его вручную (или даже погрузчиком - если большой) снимают с транспортера, стирают в базе данных его маршрут (класс, а как же!) и запускают по-новой, вплоть до того, что он получает новый баркод.
А все потому, что починить поломанный маршрут - когда это отвественная товарная операция - никто не может автоматически.
Создавать лишний класс - это ошибка.
Маршрут - а если автомобиль не доехал, что делать с незавершенным маршрутом?
Класс здесь никак не лишний. Я честно говоря не понял к чему этот аргумент вообще? Существование пакета TCP/IP никак не отменяет существование маршрутизаторов например. И пакет не хранит в себе все свои "маршруты" и "остановки". Или я что-то не знаю о сетевом программировании? :)
А данная конкретная ситуация свидетельствует, и то - ВОЗМОЖНО свидетельствует, о ошибках в проектировании. Но никак не является аргументом за хранение операций фиксирования (и назначения кстати) остановок в классе автомобиля.
А что касается товарной операции - то да, это не настолько просто - потому что требует соблюдения определенных условий. Вполне возможно, что это не ошибка программиста либо проектировщика - а требования заказчика и все такое прочее. Если ящик перемещался со склада один, на склад два - то да потеря связи с контроллером - это вполне себе нештатная ситуация. Может она пропала потому что пропала, а может потому что ящик скоммуниздили. Как это проверить программно? Поэтому и маршрут надо удалять - потому что операция не выполнена. Или по вашему ящики надо отправлять на склад до тех пор пока не будет получено подтверждение о получении - либо превышен таймаут? :):):)
Но это я к тому, что не всегда то что кажется чрезмерно сложным - на самом деле таковым является. Я не защищаю конкретную реализацию с вашими ящиками - но хочу напомнить что иногда простота - она хуже воровства. И как это связано с тем, о чем говорит ТС - я лично на данный момент не понял.
В случае с ящиками - им иногда надо проходить обязательные точки - например, обертка в полиэтилен автоматическая, взвешивание - но если весов или обертывателей два, а маршрут слишком конкретный - то ящик "зависает" при отказе и рестартом его не сдвинуть - он же не перепрыгивает в точку начала при остановке системы. Но чаще маршрут безразличен, главное чтобы быстрее доехал. Вот тут само понятие "маршрут" - мешает.
Но для учебного задания - это уже дебри.
В случае с ящиками - им иногда надо проходить обязательные точки - например, обертка в полиэтилен автоматическая, взвешивание - но если весов или обертывателей два, а маршрут слишком конкретный - то ящик "зависает" при отказе и рестартом его не сдвинуть - он же не перепрыгивает в точку начала при остановке системы. Но чаще маршрут безразличен, главное чтобы быстрее доехал. Вот тут само понятие "маршрут" - мешает.
ничего не скажу по поводу данной конкретной программы, опять же, не зная почему собственно разработчик реализовал это таким образом - возможно плохо понимал предметную область, возможно еще какие причины, опять же - возможно это было требование заказчика - но для задачи ТС понятие маршрута необходимо ИМХО. Без этого кажущееся упрощение программы приведет к ее существенному усложнению в значительном количестве случаев.
Имеется однорядный участок автострады без перекрестков. Автомобили появляются на одном конце дороги, проезжают и бесследно исчезают на другом конце. Машины стремятся двигаться с постоянными скоростями (разными для разных машин). Имеются разные типы автомобилей (разной длины, с разными интервалами типичной скорости). Автомобили можно разделить на легковые и грузовые. Легковые машины имеют повышенную начальную скорость и ограничение на максимальную длину автомобиля. Кроме того, некоторые легковые автомобили являются такси. Такси делают случайные кратковременные остановки (сажают или высаживают клиентов). Грузовые автомобили имеют пониженную начальную скорость и ограничение на минимальную длину автомобиля. Некоторые грузовые автомобили являются рейсовыми автобусами. Они делают регулярные остановки на заранее выделенных участках дорог. Кроме того, часть автомобилей (и легковые, и грузовые) являются автомобилями повышенной проходимости. Такие автомобили при остановке впереди идущего автомобиля могут съехать на обочину и на пониженной скорости (5 км/час) стараться объехать пробку, при первой же возможности пытаясь вернуться на автостраду. При сближении автомобилей на расстояние менее трех длин заднего автомобиля на каждые 15 км/час переднего автомобиля, задний автомобиль начинает тормозить, уменьшая скорость на 1 км/час каждую секунду до тех пор, пока скорости не сравняются. Если передний автомобиль тормозит, то задний снижает скорость на 15 км/час каждую секунду. Если расстояние между автомобилями превышает 10 длин заднего автомобиля, задний автомобиль увеличивает свою скорость на 5 км/час каждую секунду до тех пор, пока его скорость не сравняется с первоначальной скоростью. Программа должна имитировать заполнение автострады машинами разного типа и позволять изучать создание пробок и аварий при различной загрузке автострады. Автомобили запускаются со случайной первоначальной скоростью из допустимого интервала.
Процесс имитации может быть остановлен пользователем программы для просмотра параметров объектов:
Средняя скорость всех, легковых, грузовых автомобилей, автобусов, автомобилей повышенной проходимости.
Количество аварий и пробок.
Количество всех, легковых, грузовых автомобилей, автобусов, автомобилей повышенной проходимости.
Список всех автомобилей на трассе с выводом их состояния и возможности сортировки по скорости, пройденному расстоянию, типу автомобиля.
От себя. Делаю задание по примере в книге. Метод Move() по идее тупо к кординате x прибавляет "текущую скорость" * время (время - время одной итерации имитации). Для проверки о
1) столкновениях
2) торможении когда близко впереди авто
3) возможности съехать на обочину/на дорогу не врезавшишь
- использую метод класса "Car": CheckNext(Car c)
который смотрит на взаимное положение этих двух авто и изменяет поля текущего авто ИЛИ изменяет флаги, которые испольхуются в методе move (например, флаг возможности съехать на обочину: если на обочине находится машина по координатам, которые приведут к аварии - флаг в фалз)
Для реализации имитации используется класс AvtostradaMoving - имеет List<Car> cars;
во время каждой итерации происходит что то вроде (примерная схема):
foreach(Car c1 in cars)
foreach(Car c2 in cars)
if(c1!=c2)
c1.CheckNext(c2);
foreach(Car c in cars)
{
c.Move();
c.draw();
c.RefreshFlags();
}
схема может и дураковатая, но именно такая в примере (ну кроме "RefreshFlags" - это уже добавка)