【问题标题】:Changing abstract method signatures in inherited classes更改继承类中的抽象方法签名
【发布时间】:2011-08-01 14:40:48
【问题描述】:

想象一下,我有一个名为 Engine 的类作为抽象基类。我还有派生自它的 ElectrictEngine 和 FuelEngine 类。

我想创建一种为发动机加油的方法。 我是否应该将其作为基类级别的抽象方法并以通用方式命名,例如 fillUpEnergy?

问题是,如果我有一台电动发动机,该方法采用的参数数量与燃料发动机需要传递的参数数量不同。所以,方法的签名是不同的。

此外,是否有任何聪明的方法可以为两个引擎使用通用方法,但将其包装在更具体的名称中?例如:对于燃油发动机,“refuel”,对于电动发动机,“chargeBattery”?同时对用户隐藏通用方法?

【问题讨论】:

  • 电动和燃油发动机的 Refuel 是否有任何通用参数?

标签: c# abstract-class virtual-functions abstract-methods


【解决方案1】:

在这种情况下,我会定义你的抽象类的通用实现,这样你就会得到这样的结果:

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

那么你的实现看起来像这样:

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

或者,您可以定义一个接口,并将特定的实现传递给您的方法:

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

那么你的实现看起来像这样:

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

【讨论】:

  • 虽然第一个解决方案直接解决了参数问题,但它使基类无用。接口方案要好很多。
【解决方案2】:

更多地考虑如何使用这些类。如果您的客户不知道他们正在处理什么样的引擎 - 他们有一个“引擎”,那么您必须找出一个可以使用的“加油”签名。另一方面,如果您必须为每种加油使用不同的参数,那么您不能在基类中做任何事情,而必须让您的客户知道它是哪种引擎并传递正确的参数。

【讨论】:

    【解决方案3】:

    你可以有一个需要接口的加油方法吗?

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

    你们这两种加油都取什么参数?

    【讨论】:

    • 这很聪明。看看 IFuel 如何被普遍使用会很有趣。
    • 取决于其他两种方法采用的参数,这可能是可能的。 IFuel 接口可以有一个方法,例如返回一个小数的燃料量。
    • 是的。我在想,如果“加油”涉及不洒任何东西或不在雨中加油,那它仍然是引擎式的。
    【解决方案4】:

    我会将发动机和可加油/可充电的部件分开。或者您必须概括有关引擎的所有内容。例如,您可以创建另一个抽象类型(或接口)Charge,并将其传递给recharge 方法(在父抽象Engine 类中定义)。如果您需要一些代码,请告诉我。

    【讨论】:

    • 只是按照这些思路输入了一些内容。我在想一个 TorqueProducer,它接受一个 PowerSource 参数。
    【解决方案5】:

    抽象类确实不合适,因为 Refuel 不是一个将 sum 类型作为参数的函数(方法)。

    这样的事情怎么样?

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

    【讨论】:

      猜你喜欢
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 2013-07-01
      • 1970-01-01
      • 2013-11-28
      • 2013-08-25
      相关资源
      最近更新 更多