C# 如何创建具有不同签名的多态方法
假设我有一些抽象的C# 如何创建具有不同签名的多态方法,c#,oop,inheritance,polymorphism,C#,Oop,Inheritance,Polymorphism,假设我有一些抽象的
类和从车辆
派生的汽车、卡车、摩托车抽象类。还可以想象,我必须能够为卡车和摩托车制造一辆燃料汽车或电动汽车等等。(混凝土类)
两个问题:
考虑到我想用一种多态的方式来填充车辆中的能量而不知道它是什么。例如,如果车辆以燃油为基础,我想给它加注燃油,并且该方法应具有3个参数:void FillUpEnergy(EfuelType i_fuelType,int-amounOfEnergy,int-maxAmountOfEnergy)
但对于电动汽车,我需要几乎相同的功能标志,但这次没有燃油类型,例如(2个参数):
我可以使用上述约束条件执行polymorhicFillUpEnergy
方法吗?(不同方法的签名)
2.在我的实现中,所有具体类都包含对Engine
(另一个抽象类)的引用,它表示FuelEngine
或ElectricEngine
(我拥有的其他具体类派生自Engine)。例如,我有一个名为ElectricCar
的具体类,其中包含对ElectricEngine
的引用这种架构足够好吗?或者有更好的方法来实现车库系统吗? (在面向对象设计等方面)关于问题1) 您可以将电力/汽油作为fueltype的一部分,并在您的域逻辑中处理它 C#不提供具有不同签名的多态性 2) 这就是作文
什么是
电动汽车
与燃油汽车
的区别?只有引擎(概念上):
典型的组合与继承示例。命名有点奇怪,因为发动机正在加油。。。但这不是重点。关于1)拥有
FillUpEnergy
polymorphic()的意义在于,当您只知道对象是Vehicle
时,就能够调用此方法
如果您需要知道确切的类型以选择正确的参数集,那么这个函数不需要多态
大约2)没有什么令人震惊的你不能用不同的签名制作多态的“推式”方法,但是你可以用广为人知的方法制作多态的“拉式”方法 想法是颠倒交互顺序,让汽车对象决定做什么:不要调用
FillUpEnergy
,给汽车你认为它需要的东西,而是调用FillUpEnergy
,让汽车得到它知道它需要的东西,如下所示:
interface IEnergyProvider {
void TakeFuel(EfuelType i_fuelType, int amounOfEnergy);
void TakeElectricity(int amounOfEnergy);
}
interface ICar {
void FillUpEnergy(IEnergyProvider provider);
}
现在,多态方法的签名是固定的,但方法的分派需要两条腿而不是一条腿:
- 您可以调用myCar.FillUpEnergy(myProvider)
- 汽车呼叫
或myProvider.TakeFuel
myProvider.takeelectronic
填充能量方法反映了这一点。在这种情况下,汽车是聚合根。正如德米特定律所说,你们不应该单独使用引擎,只能通过汽车物体。这里的灌木丛完全被打破了。
interface IEngine
{
void FillUpFuel(int amountOfFuel, int maxAmountOfFuel);
}
class ElectricEngine : IEngine
{
public void FillUpFuel(int amountOfFuel, int maxAmountOfFuel) { ... }
}
abstract class Vehicle
{
public abstract IEngine Engine { get; }
}
class Car : Vehicle
{
public IEngine _engine;
public override IEngine Engine { get { return _engine; } }
public Car(IEngine engine)
{
_engine = engine;
}
}
...
var electricCar = new Car(new ElectricEngine());
electricCar.Engine.FillUpFuel(40, 70);
interface IEnergyProvider {
void TakeFuel(EfuelType i_fuelType, int amounOfEnergy);
void TakeElectricity(int amounOfEnergy);
}
interface ICar {
void FillUpEnergy(IEnergyProvider provider);
}