Hello to everyone! I have some problem with organizing classes properly.
Suppose, I have some class ABase. When I want to create some different (more particular) abstraction of this class (denote it AParticular), I can use inheritance or just composition. Then it is easy to treat AParticular as ABase: in case of inheritance it is made automatically, in case of composition I can create some const ABase& AParticular::GetABasePart()
method. By this I avoid code duplication and get polymorphic features.
But, when I have two or more classes that interact with each other, I have some problems to create analogues of these classes in a more particular abstraction. For example, suppose, I have two classes Car and Station. Station has some public methods to maintain cars:
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;
}
Now, I want to create Truck and TruckStation classes: they are pretty similar to Car and Station classes and have minor changes. To understand problem it is sufficient to think as they do absolutely the same as Car and Station classes, but their methods have a bit other name (i.e. TruckStation::AddTruckToPlaceNumberN instead of Station::AddCarToPlaceNumberN)
How to organize the code of new classes to provide these features?
- No code duplication, I want to use the already created Car and Station class methods.
- Fast conversion Truck& -> Car&, TruckStation& -> Station& (Not necessary inheritance, composition is suitable also), since I want sometimes to treat Truck as Car and TruckStation as Station.
- All interaction methods in level Car-Station should be realized in a new level Truck-TruckStation.
The main problem is the 3d item. Let's consider two interaction methods:
1) It is ok with this method:
// 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) But I don't know how to implement the analogue of 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*.
}
Repeat the question: how can I implement these classes to provide:
- no code duplication.
- Possibility to treat new classes as their higher level abstractions.
- Implementation methods such as TruckStation::GetMutableTruckPointer() that correspond to Station::GetMutableCarPointer().
Tnx!