我对C#中的这一小段代码有疑问(假设函数ManageCars在MainProgram中)。 代码应该可行,但我的问题是:这是使用多态的正确方法吗?从Car转投法拉利是不正确的还是编程方式不好?我发现的唯一问题是我需要一个很长的开关/箱来管理所有类型(法拉利,梅赛德斯......)。 你有什么看法?
class Car
{
string _plate = "";
public string Plate
{
get { return _plate; }
set { _plate = value; }
}
}
class Ferrari : Car
{
string specialName = "";
public string SpecialName
{
get { return specialName; }
set { specialName = value; }
}
Ferrari (Car obj )
{
specialName = (obj is Ferrari) ? ((Ferrari)obj).SpecialName : "";
}
}
static void ManageCars (Car A)
{
if (A is Ferrari)
{
Ferrari B= (Ferrari) A;
Console.Writeline("This is a Ferrari! specialName is " + B.SpecialName);
}
//else if(A is Mercedes)
//{
...
//}
else
{
Console.Writeline("This is simple car");
}
}
答案 0 :(得分:1)
在课堂上,您应该创建如下虚拟函数:
public virtual void ManageCars()
{
Console.Writeline("This is simple car");
}
所有派生类都可以通过覆盖基类方法来实现派生功能。例如:
public override void ManageCars()
{
Console.Writeline("This is a Ferrari! specialName is " + B.SpecialName);
}
然后,对于每辆派生汽车,您只需调用ManageCars,无需任何开关声明。
答案 1 :(得分:1)
我建议不要在这种情况下使用多态性。你最终会得到很多子类。创建一个汽车类,并添加诸如“制造”,“模型”,“颜色”,“马力”等属性。相信我,从经验来看,这将为您节省许多令人头疼的事。
话虽如此,是的,您可以使用“as”运算符来检查基类是否是子类的实例,但它通常表明架构是坏的。
答案 2 :(得分:1)
使用多态时,通常在需要检索特殊方法时使用从基类到专用类的转换。例如假设你有
public class Batmobile: Car
{
public void fly()
{
// flying algo here
}
}
然后,如果要迭代基类型的集合,并且需要在可能的情况下应用特殊行为,则可以从基类转换为专用类并调用特殊行为
例如:
Car[] cars = new Car[];
// Retrieve your cars collection here
foreach (Car car in cars)
{
if (car is BatMobile)
{
BatMobile batCar = (BatMobile)car;
batCar.fly(); // No way to invoke this method unless we are sure it's
// a BatMobile
}
}
但是在上面提到的情况下,最好利用虚拟方法调用和后期绑定来利用C#语言的多态能力。
如@Jonathan Riger所示,您创建了一个类似ManageCars的虚拟方法,然后在每种特殊类型的后代中覆盖它。凭借运行时的多态性,将使用来自基类的编译时调用从相应的实例调用正确的方法
例如
Car class中的:
public virtual void ManageCars()
{
Console.Writeline("This is simple car");
}
法拉利课程:
public override void ManageCars()
{
Console.Writeline("This is a Ferrari! specialName is " + B.SpecialName);
}
在BatMobile类中:
public override void ManageCars()
{
Console.Writeline("This is a BatMobile car, it can fly really high !");
}
现在假设我们有:
Car[] cars = new Car[3];
cars[0] = new Car();
cars[1] = new Ferrari();
cars[2] = new BatMobile();
如果循环遍历数组并调用ManageCar()方法,例如:
foreach (Car car in cars)
{
car.ManageCars();
}
...它将在运行时检索正确的方法,即使编译时调用是基于不知道方法特化的基类:它是多态性魔法的一部分:)