I'm hitting a wall in a complex project with a few abstractions implied. For privacy purposes, I have tried to translate the items in my problem to more common ones, so it may sound a bit ridiculous, but I assure you it makes sense in its original context.
Here goes.
Let's say I have freight transportation (eg. planes and cargo ships)
public abstract class Freight { }
public class Ship: Freight { }
public class Plane: Freight { }
Now by design choice, freight transportation is meant to transport vehicles. So all freight will have a list or array of vehicles. (let's choose list, in our case)
public abstract class Vehicle { }
public abstract class Freight
{
public List<Vehicle> vehicles { get; }
}
Then, also by design choice, it is decided that Planes are only meant to transport Motorbikes, and Ships are only meant to transport Cars. And this is where my question arises. How do I do that ?
My first though was to abstract the list property in the freight, so that it needs to be overriden in specific freight (maybe detailing how it gets loaded differently into the freight), but in doing, I haven't found a way to specify or constraint the content of the abstract list from freight, that ensures all freight must have its list of vehicles.
public abstract class Vehicle { }
public class Motorbike : Vehicle { }
public class Car : Vehicle { }
public abstract class Freight
{
// This becomes abstract, maybe ?
public abstract List<Vehicle> vehicles { get; }
}
public class Cargo: Freight
{
// Tentative #1
public override List<Vehicle> vehicles where Vehicle : Car { get; }
}
public class Plane: Freight
{
// Tentative #2
public override List<Motorbike> vehicles { get; }
}
But none of these seem to work.
My question is : Are there abstraction design concepts that would allow me to reach specifications / constraints goals that I should know and would help me that I am missing ?. Or are there any official (Microsoft) recommendations on this kind of topic on alternative designs to achieve expected behavior ?
To try and clarify the concept is the following (edited after answer) : The piece of software tries to mimic rules and behaviour of non software. These are described in its own documentation, and the ruleset makes sense for a physical product, its application, and how/what restrictions applies to it during its manufacturing process. I translated this concept to freight transportation because it's the only "simple" example I had in mind, without going in the details of what product my company is manufacturing, and why are these restriction the way they are.
I hope I have been clear enough, I find this as difficult to explain as it is to find a solution for. So I thank you for your trying to understand.
Thank you very much.
CodePudding user response:
This sounds like a job for generics. Instead of making a list of Vehicle
, you can give Freight
a list of T
, and then constrain T
to be a subclass of Vehicle
:
public abstract class Vehicle { }
public class Motorbike : Vehicle { }
public class Car : Vehicle { }
public abstract class Freight<T>
where T: Vehicle
{
public List<T> Vehicles { get; }
}
public class Ship: Freight<Car>
{
}
public class Plane: Freight<Motorbike>
{
}