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();
}
}
}
首先你必须从基类中删除virtual
Visit v=new Pickup();
v.customeraddress = "some address";
v=new Delivery();
v.customeraddress = "some address";
正如您在上面的示例中看到的,v
是Visit
的一种类型,但我允许将其指向Pickup
或Delivery
的实例,它们对分配的实例类型具有不同的行为。
如果我理解正确的话…
您的场景是您有一个Visit
对象,并希望根据它是Pickup
还是Delivery
获得详细信息。只要在运行时创建了Delivery
或Pickup
对象,就可以执行以下操作:
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
对象没有意义,它要么是Pickup
或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())
然而,如果你想使用特定于传递的属性,你不能使用它,因为对例如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
成员,则需要将向下转换!