Changing abstract method signatures in inherited classes
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 开发者_C百科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?
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;
}
}
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.
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?
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.
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);
}
}
精彩评论