繁体   English   中英

C#多态

[英]c# polymorphism

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

我有三节课。 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();
    }
}
}

首先,您必须从基类中删除virtual

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

如您在上面的示例中看到的, v是一种Visit类型,但我允许它指向一个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或Enumeration类。 然后,您可以查看此变量并进行相应的操作-但需要先创建投射对象,然后才能使用它。 如果这对您来说是个问题,我可以举个例子。

如果您不希望实例化基类(即, 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()) 

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

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成员,则需要对其下调!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM