2

我是多态的新手并且有点挣扎。

我有三个班。作为基类的访问类。然后是送货和取货。

送货和取货都是拜访。

我希望能够参考访问课程并与送货和取货交谈。

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

4 回答 4

0

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

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

正如您在上面的示例中看到的那样,它v是一种类型,Visit但我允许它指向一个实例PickupDelivery对分配的实例类型具有不同的行为。

于 2012-12-20T10:16:30.563 回答
0

如果我正确理解你的问题......

您的场景是您有一个Visit对象,并希望根据它是 aPickup还是Delivery. 只要您在运行时创建了DeliveryorPickup对象,您就可以执行以下操作:

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

然后您可以使用该对象,该对象通过设计将向您显示访问变量以及该类的唯一变量..例如...d.customeraddress

当从现有源(例如平面文件或数据库)获取访问对象时,这不起作用。如果是这种情况,如果您打算进一步增加分类,您将需要类中的属性,Visit例如Enumeration 类。bool AmIDelivery然后,您可以查看此变量并采取相应的行为 - 但您需要先创建转换对象才能使用它。如果这对你来说是个问题,我可以举个例子。

于 2012-12-20T10:22:33.503 回答
0

如果您希望您的基类不被实例化(即Visit对象没有意义,它是 aPickup或 a Delivery)您可以将基类声明为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()) 

但是,如果您想使用特定于交付的属性,则不能使用它,因为对 eg 的引用visits[0]是 type Visit,即使引用的对象是 type 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
   }
}
于 2012-12-20T10:23:39.233 回答
0

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

在您的情况下,除了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# 是一种静态类型语言,因此类型化意味着类型为 as 的变量Visit可以访问它自己的成员。如果你需要访问Delivery会员,你需要向下投!

于 2012-12-20T10:31:07.067 回答