Changing abstract method signatures in inherited classes
Asked Answered
S

5

12

Imagine I have a class called Engine as an abstract base class. I also have ElectrictEngine and FuelEngine classes which derive from it.

I want to create a method for refueling the engine. Should I do it as an abstract method on the base class level and name it in a generic fasion, such as fillUpEnergy?

The problem is that if I have an electric engine, the number of parameters which the method takes is different from the number of parameters which need to be passed for a Fuel Engine. So, the method's signature is different.

In addition, is there any smart way to use the generic method for both engines but to wrap it in a more specific name? For example: for a fuel Engine, "refuel", and for an electric engine, "chargeBattery"? And at the same time hide the generic method from the user?

Serpasil answered 8/4, 2011 at 15:12 Comment(1)
Are there any common parameters to Refuel for the Electric and Fuel engines?Mosley
W
6

In this situation, I would define a generic implementation of your abstract class, such that you get something like this:

public abstract class EngineBase<T>
{
     public abstract void Refuel(T parameters);
}

Then your implementations look like this:

public class ElectricEngine : EngineBase<ElectricParameters>
{
     public override void Refuel(ElectricParameters parameters) { }
}

Alternatively, you can define an interface, and pass a specific implementation to your methods:

public abstract class EngineBase
{
     public abstract void Refuel(IRefuelParameters parameters);
}

Then your implementations look like this:

public class ElectricEngine : EngineBase
{
     public override void Refuel(IRefuelParameters parameters)
     {
          if(!(parameters is ElectricParameters))
              throw ApplicationException("Not the right params!");

          ElectricParameters rightParams = parameters as ElectricParameters;
     }
}
Wetmore answered 8/4, 2011 at 15:17 Comment(1)
While the first solution directly solves the issue with the parameters, it makes the base class useless. The interface solution is much better.Rellia
F
2

Think more about how you will use these classes. If your client won't know what kind of engine they're dealing with - they have an 'Engine' then you have to figureo out a 'refuel' signature that boht can use. if on the other hand you HAVE to have different args for each kind of refueling, then you can't do anything in the base class and have to instead have your client know what kind of engine it is and pass the right args.

Fiddlestick answered 8/4, 2011 at 15:15 Comment(0)
M
2

You could have a method to refuel that takes an interface?

eg
public void Refuel(IFuel fuel)
{
//do refueling logic
}

What parameters do your two types of refueling take?

Michi answered 8/4, 2011 at 15:15 Comment(3)
This is clever. It will be very interesting to see how IFuel can be used generically.Fiddlestick
depending on what parameters the other two methods would take it may be possible. The IFuel interface could have a method that returns a decimal for the amount of fuel increate for exampleMichi
Yeah. I was thinking if 'fueling' involved not spilling any or not doing it in the rain it's still engine-type-ish.Fiddlestick
L
0

I would separate the engine and the refuel-able/rechargeable parts. Or you have to generalize all the things concerning the engine. For example, you can make another abstract type (or interface) Charge, and pass this to recharge method (which is defined in the parent abstract Engine class). Let me know, if you need some code.

Lizzielizzy answered 8/4, 2011 at 15:23 Comment(1)
Was just typing something along those lines. I was thinking of a TorqueProducer which takes a PowerSource argument.Evaporation
B
-1

An abstract class really isn't appropriate because Refuel is not a function (method) that takes a sum type as a parameter.

How about something like this?

interface IEngine
{
    void Refuel(FuelingStation station);        
}

class FuelingStation
{
    double Gas;
    double Air;
    double Charge;


    private double GetFuel(ref double fuel, double requested)
    {
        var temp = Math.Max (0, fuel - requested);

        fuel -= temp;

        return temp;
    }


    public double GetGas(double requestedAmount)
    {
        return GetFuel (ref Gas, requestedAmount);

    }

    public double GetAir(double requestedAmount)
    {
        return GetFuel (ref Air, requestedAmount);
    }

    public double GetCharge(double requestedAmount)
    {
        return GetFuel (ref Charge, requestedAmount);
    }
}


class GasEngine : IEngine
{

    double Tank;
    double Capacity;


    public void Refuel(FuelingStation station)
    {
        Tank = station.GetGas (Capacity - Tank);
    }
}


class Electric : IEngine
{

    double Charge;
    double ChargeCapacity;

    double Tank;
    double TankCapacity;



    public void Refuel(FuelingStation station)
    {
        Tank = station.GetGas (TankCapacity - Tank);
        Charge = station.GetCharge (ChargeCapacity - Charge);
    }
}
Boroughenglish answered 9/4, 2011 at 3:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.