很多人常把多态和继承混淆起来,实际上二者区别较大,一个明显的例证便是,VB 6.0中没有继承,但有多态。一般的理解是,继承强调的是自上而下的\"血缘关系",是"是一个""是一种"的关系;而多态只强调两个对象在行为上的相似性,而不管这两个对象之间是什么关系。有继承关系的对象一般都有多态关系,而有多态关系的对象间未必有继承关系。比如,马有跑的行为,蒙古马和伊犁马都是马的一种,它们都与马有继承关系,都有跑这个行为,在\"跑\"这个意义上,它们有多态关系。同样,机器猫也能跑,机器猫与马在跑这个行为上有多态关系,但它们没有继承关系。
VB 6.0中有两种方法可以实现多态,即后期绑定和接口。在本套书的VB篇中我们大量采用了接口这种方法来实现多态。在性能上,它比用后期绑定实现要好些。.NET 中还可以通过继承和.NET 反射来实现多态,下面主要介绍继承和接口这两种实现途径。
用继承实现多态
在2.2节介绍继承时创建了基类CGElement和派生类CLine。下面再创建一个派生类CRectangle。CRectangle类用于定义矩形的特征和方法。为了演示多态,这里只添加一个无参构造函数和一个Drw方法。Daw方法重 了基人的Draw方法。
【VB.NET】
Public Class CRectangle
Inherits CGElement
Public Sub New()
End Sub
Public Overrides Sub Draw()
text-blue-400">Console.text-blue-400">WriteLine("绘矩形。")
End Sub
End Class
【VC#.NET】
public class CRectangle:CGElement
{
public Crectangle()
{
}
public override void Draw()
{
Console.WriteLine("绘矩形。"):
}
}
然后在Form1类中添加下面的代码,创建两个CGElement类型的变量并分别作为一个CLine人实例和一个CRectangle子例的引用,然后调用CGElement 的 Drw方法绘制直线段和矩形。
【VB.NET】
Private Sub Form1_Load(ByVal sender As System.0bject,
ByVal text-blue-400">e As System.EventArgs) Handles MyBase.Load
Dim ge1 As CGElement = New CLine()
Dim ge2 As CGElement = New CRectangle()
gel.Draw()
ge2.Draw()
End Sub
【VC#.NET】
private void Form1_Load(object sender, System.EventArgs e)
{
CGElement ge1= new CLine();
CGElement ge2= new CTectangle();
ge1.Draw();
ge2.Draw();
}
程序运行结果如图2-4所示。可见,由于实现了多态,可以自动区分是绘制直线段还是绘制矩形。
图2-4用继承实现多态
2.4.2用接口实现多态
沿用2.3节的例子,仿照2.4.1节添加CRectangle类,它实现了IGElement接口。
【VB.NET】
Public Class CRectangle
Implements IGElement
Private m_ID As Integer
Public Property ID() As Integer Implements IGElement,ID
Get
Return m_ID
End Get
Set(ByVal Value As Integer)
m_ID =Value
End Set
End Property
Public Sub Draw() Implements IGElement.Draw
text-blue-400">Console.text-blue-400">WriteLine("绘矩形。")
End Sub
End Class
【VC#.NET】
public class CRectangle:IGElement
{
private int m_ID;
public int ID
{
get{retum m_ID;}
set{m_ID = value:}
}
public void Draw()
{
Console.WriteLine("绘矩形。");
}
}
在Form1类中添加下面的代码,对实现了IGElement接口的类进行测试。
【VB.NET】
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal text-blue-400">e As System.EventArgs) Handes MyBase.Load
Dim ge1 As IGElement = New CLine()
Dim ge2 As IGElement = New CRectangle()
ge1.ID=1
ge2.ID =11
text-blue-400">Console.text-blue-400">WriteLine("ID:{0},{1}", ge1.ID,ge2.ID)
ge1.Draw()
ge2.Draw()
End Sub
【VC#.NET】
private void Form1_Load(object sender, System.EventArgs e)
{
IGElement ge1= new CLine();
IGElement ge2=new CRectangle();
ge1.ID=1;
ge2.ID=11;
Console.WriteLine("ID:{0},{1}", ge1.ID, ge2.ID);
ge1.Draw();
ge2.Draw();
}
程序运行结果如图2-5所示。可见,利用接口也能很好地实现多态。
图2-5 用接口实现多态
两种方式的比较
上面两种方式都能实现多态,而且性能相近。一般来说,当对象存在继承关系时用继承实现多态,不存在继承关系时用接口实现多态。