简体   繁体   English

更改继承类中的抽象方法签名

[英]Changing abstract method signatures in inherited classes

Imagine I have a class called Engine as an abstract base class. 想象一下,我有一个名为Engine的类作为抽象基类。 I also have ElectrictEngine and FuelEngine classes which derive from it. 我也有ElectrictEngine和FuelEngine类来自它。

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? 我应该将它作为基类级别的抽象方法,并将其命名为通用的fasion,例如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"? 例如:对于燃料发动机,“加油”,对于电动发动机,“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). 例如,您可以创建另一个抽象类型(或接口) Charge ,并将其传递给recharge方法(在父抽象Engine类中定义)。 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. 抽象类确实不合适,因为Refuel不是将sum类型作为参数的函数(方法)。

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM