У меня проблемы с организацией классов.
Предположим, у меня есть класс ABase.Когда я хочу создать какую-то другую (более конкретную) абстракцию этого класса (обозначим это AParticular), я могу использовать наследование или просто композицию.Тогда к AParticular легко относиться как к ABase: в случае наследования это делается автоматически, в случае композиции я могу создать какой-то const ABase& AParticular::GetABasePart()
метод.Благодаря этому я избегаю дублирования кода и получаю полиморфные функции.
Но когда у меня есть два или более классов, которые взаимодействуют друг с другом, у меня возникают некоторые проблемы с созданием аналогов этих классов в более конкретной абстракции.Например, предположим, у меня есть два класса Car и Station.В Station есть несколько общедоступных методов обслуживания автомобилей:
class Car {
...
}
class Station {
...
void AddCarToPlaceNumberN(const Car& car, int place_number) {
// adds car to some_container<Car>.
}
Car* GetMutableCarPointer(int place_number) {
// gets mutable pointer from some_container<Car>.
}
...
some_container<Car> cars;
}
Теперь я хочу создать классы Truck и TruckStation: они очень похожи на классы Car и Station и имеют небольшие изменения.Чтобы понять проблему, достаточно подумать, поскольку они делают абсолютно то же самое, что и классы Car и Station, но их методы имеют немного другое имя (например, TruckStation :: AddTruckToPlaceNumberN вместо Station :: AddCarToPlaceNumberN)
Как организоватькод новых классов, обеспечивающих эти функции?
- Нет дублирования кода, я хочу использовать уже созданные методы класса Car и Station.
- Быстрое преобразование Truck & -> Car &, TruckStation &-> Station & (Необязательное наследование, состав также подходит), поскольку иногда я хочу трактовать Truck как Car, а TruckStation как Station.
- Все методы взаимодействия на уровне Car-Station должны быть реализованы на новом уровне Truck.-TruckStation.
Основная проблема - это 3-й предмет.Давайте рассмотрим два метода взаимодействия:
1) С этим методом все в порядке:
// If we use inheritance in creating Truck and TruckStation, then we just run
void TruckStation::AddTruckToPlaceNumberN(const Truck& car, int place_number) {
AddCarToPlaceNumberN(car, place_number)
}
// If we use composition, then it is appropriate to run sth like that:
void TruckStation::AddTruckToPlaceNumberN(const Truck& car, int place_number) {
station_.AddCarToPlaceNumberN(car.GetCarPart(), place_number);
}
2) Но я не знаю, как реализовать аналог Station :: GetMutableCarPointer ():
// For example, if TruckStation was inherited from Station, then suppose:
Truck* TruckStation::GetMutableTruckPointer() {
Car* car = GetMutableCarPointer();
// Ups! I need to return Truck*, not Car*.
}
Повторите вопрос: как я могу реализовать эти классы, чтобы обеспечить:
- без дублирования кода.
- Возможность рассматривать новые классы как их высшиеабстракции уровней.
- Методы реализации, такие как TruckStation :: GetMutableTruckPointer (), которые соответствуют Station :: GetMutableCarPointer ().
Tnx!