c# polymorphism

本文关键字:polymorphism | 更新日期: 2023-09-27 17:49:01

我是多态新手,有点挣扎。

我有三个类。Visit类是基类。然后是送货和取货。

送货和取货都是拜访。

我希望能够参考访问类,并讨论交付和提取。

    public virtual class Visit
    {
    private string customerName;
    private string customerAddress;
    private DateTime arrivalTime;
    public string customername
    {
        //name properties
        set { customerName = value; }
        get { return customerName; }
    }
    public string customeraddress
    {
        //address properties
        set { customerAddress = value; }
        get { return customerAddress; }
    }
    public DateTime arrivaltime
    {
        //time proerties
        set { arrivalTime = value; }
        get { return arrivalTime; }
    }
}
public class Delivery : Visit
/*
 * Polymorphism, Delivery is also a visit.
 */
{
    private string deliveryAddress;
    private string deliveryName;
    public string deliveryaddress
    {
        set { deliveryAddress = value; }
        get { return deliveryAddress; }
    }
    public string deliveryname
    {
        set { deliveryName = value; }
        get { return deliveryName; }
    }
    public string ToString()
    { //return Delivery details
        return deliveryname + " " + deliveryaddress + " " + customername + " " + customeraddress + " " + arrivaltime;
    }
}
public class Pickup : Visit
/*
 * Polymorphism, pickup is also a visit.
 */
{
    public string ToString()
    { //return Pickup details
        return customername + " " + customeraddress + " " + arrivaltime.ToString();
    }
}
}

c# polymorphism

首先你必须从基类中删除virtual

Visit v=new Pickup();
v.customeraddress = "some address";
v=new Delivery();
v.customeraddress = "some address";

正如您在上面的示例中看到的,vVisit的一种类型,但我允许将其指向PickupDelivery的实例,它们对分配的实例类型具有不同的行为。

如果我理解正确的话…

您的场景是您有一个Visit对象,并希望根据它是Pickup还是Delivery获得详细信息。只要在运行时创建了DeliveryPickup对象,就可以执行以下操作:

Visit v = GetVisit() //or whatever your method is
if(v.GetType() == typeof(Delivery))
{
    Delivery d = v as Delivery;
}
else //Must be Pickup
{
    Pickup p = v as Pickup;
}

然后可以使用对象,它将按照设计向您显示Visit变量以及该类的唯一变量。例如……d.customeraddress

当Visit对象是从已经存在的源(如平面文件或数据库)中获取时,这不起作用。如果是这种情况,则需要在Visit类(如bool AmIDelivery)中添加一个属性;如果计划进一步增加分类,则需要在枚举类中添加一个属性。然后您可以查看这个变量并做出相应的行为——但是您需要在使用它之前创建强制转换对象。如果这对你来说是一个问题,我可以给你看一个例子。

如果你想要你的基类不被实例化(即Visit对象没有意义,它要么是PickupDelivery)你可以声明基类为abstract而不是virtual

之后,你可以随心所欲地使用多态代码。例如:

List<Visit> visits = new List<Visit>();
visits.Add(new Pickup{ ... some properties set here ...});
visits.Add(new Delivery{ ... some properties set here ...});
// writes out a pickup via a polymorphic call
Console.WriteLine(visits[0].ToString()) 
// writes out a delivery via a polymorphic call
Console.WriteLine(visits[1].ToString()) 

然而,如果你想使用特定于传递的属性,你不能使用它,因为对例如visits[0]的引用是Visit类型的,即使引用的对象是Delivery类型。要使用它们,您需要检查对象的运行时类型,并将它们强制转换为特定的子类型,如下所示:

foreach (Visit visit in visits)
{
   if (visit is Delivery)
   {
       Delivery d = (Delivery)visit;
       //delivery specific code here
   }
   else if (visit is Pickup)
   {
       Pickup p = (Pickup) visit;
       //pickup specific code here
   }
   else
   {
       //unknown descendant, panic
   }
}

多态性意味着基类中的实现可以在派生类中被覆盖。

在您的示例中,除了ToString()重写之外,所有内容都是关于继承

请注意,在代码中隐藏了ToString()方法。c#允许您使用父类的确切标识符向继承的类添加成员,但这不是多态性。

您的派生类将做多态性如果整个ToString()被标记为overrides关键字:

public override string ToString()
{
    return base.ToString(); // Change this line with any custom action
}

另一个细节是类不能是虚的,但成员可以。类可以是regular(允许多态性)或sealed(不能继承)。

嗯…你知道向上向下是什么吗?

向下类型转换

将引用强制转换为更具体的类型。例如:

Visit visit = new Delivery();
Delivery delivery = (Delivery)visit; // This is a downcast!

向上转型

将引用强制转换为不太具体的类型。例如:

Visit deliveryTypedAsBaseClass = new Delivery() // This is an upcast!

然后,由于c#是一种静态类型语言,类型意味着类型为Visit的变量可以访问它自己的成员。如果您需要访问Delivery成员,则需要将向下转换!