c#多态性.从基类强制转换为派生类
本文关键字:转换 派生 多态性 基类 | 更新日期: 2023-09-27 18:15:21
我对c#中的这一小段代码有一个问题(假设函数ManageCars在MainProgram中)。代码应该可以工作,但我的问题是:这是使用多态性的正确方法吗?从《Car》到《Ferrari》是正确的还是一种糟糕的编程方式?我发现的唯一问题是,我需要一个很长的开关/盒子来管理所有类型(法拉利,梅赛德斯…)。你的意见是什么?
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");
}
}
在您的类中,您应该创建如下的虚函数:
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,而不需要任何switch语句。
我建议在这种情况下不要使用多态性。你最终会得到很多子类。创建一个car类,并添加诸如"Make"、"Model"、"Color"、"马力"等属性。从我的经验来看,相信我,这将为你在未来省去许多麻烦。
已经说过,是的,你可以使用"as"操作符来检查一个基类是否是子类的实例,但它通常是一个体系结构不好的指示符。
使用多态性时,通常在需要检索特殊方法时使用从基类到专门化类的强制转换。例如,假设您有
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这样的虚拟方法,然后在每个特殊类型的后代中重写它。通过运行时的多态性,将通过基类
的编译时调用从相应的实例调用正确的方法。例如in Car class:
public virtual void ManageCars()
{
Console.Writeline("This is simple car");
}
Ferrari class:
public override void ManageCars()
{
Console.Writeline("This is a Ferrari! specialName is " + B.SpecialName);
}
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();
}
…它将在运行时检索正确的方法,即使编译时调用基于不知道方法专门化的基类:这是多态性魔法的一部分:)