Search code examples
c#oopinheritancepolymorphism

How can I make a polymorphic method with different signatures


Consider I have some abstract Vehicle class and car, truck, motorcycle abstract classes which derive from Vehicle. Also imagine that I have to be able to create a fueled based car or electric based car and so on for truck and motorcycle as well. (concrete classes)

Two questions:

1.Consider that I want to fill up energy in a vehicle without knowing what it is, in a polymorphic way. For example if the vehicle is fuel based I want to fill it with fuel and the method should be with 3 parameters:
void FillUpEnergy(EfuelType i_fuelType,int amounOfEnergy, int maxAmountOfEnergy)

but for electricy based vehicle I need almost the same function signture but this time without fuel type of course, for example (2 parameters):

void FillUpEnergy(int amounOfEnergy, int maxAmountOfEnergy) 

Can I do a polymorhic FillUpEnergy method with the above constraints? (different method's signatures)

2.In my implementation all the concrete classes hold a reference for Engine(another abstract class) which represent a FuelEngine or ElectricEngine (other concrete classes I have which derive from Engine). For example I have a concrete class named ElectricCar which holds a reference for ElectricEngine.
Is this architecture good enough or are there better ways to implement a garage system? (In terms of Object oriented design etc..)


Solution

  • You cannot make a polymorphic "push-style" method with different signatures, but you can make a polymorphic "pull-style" method using the well-publicized Visitor Pattern.

    The idea is to invert the sequence of interaction, and let the car object decide what to do: Instead of calling FillUpEnergy and giving the car what you think it needs, call FillUpEnergy and let the car take what it knows it needs, like this:

    interface IEnergyProvider {
        void TakeFuel(EfuelType i_fuelType, int amounOfEnergy);
        void TakeElectricity(int amounOfEnergy);
    }
    interface ICar {
        void FillUpEnergy(IEnergyProvider provider);
    }
    

    Now the signature of your polymorphic method is fixed, but the dispatch of the method takes two legs instead of one:

    • You call myCar.FillUpEnergy(myProvider)
    • The car calls myProvider.TakeFuel or myProvider.TakeElectricity