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

c#多态性.从基类强制转换为派生类

在您的类中,您应该创建如下的虚函数:

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

…它将在运行时检索正确的方法,即使编译时调用基于不知道方法专门化的基类:这是多态性魔法的一部分:)