类是描述对象特征的代码。作为对象来说,一方面它有很多自身的特点,有一些固有属性,另一方面,它要与其他对象进行交互,发生联系,会产生一系列的行为。而且,当某种行为发生在它上面时,可能会发生一些事件,产生一定的后果。所以,用代码来描述对象时,就需要考虑这些问题,并进行抽象、概括和组织。本节主要介绍类的相关概念和实现方法。
属性
属性描述对象的特征,它是一种特殊的方法,用于设置和读取对象的值。下面创建一个CPosition类,它有一个x属性和一个y属性,分别定义点的横坐标和纵坐标,定义代码如下:
【VB.NET】
Public Class Position
Private m_x, m_y As Single
Private m_ID As Integer
Public Property x() As Single
Get
Return m_x
End Get
Set(ByVal Value As Single)
m_x=Value
End Set
End Property
Public Property y() As Single
Get"
Return m_y
End Get
Set(ByVal Value As Single)
m_y = Value
End Set
End Property
【VC#.NET】
public class Positior
{
private float m_x,m_y;
private int m_ ID;
public float x
{
get{return m_x;}
set{m_x= value;}
}
public float y
{
get{return m_y:}
set{m_y = value;}
}
从上面的代码中可以看出,在VB.NET代码中,读写属性的语句是集中在一个过程中的,这与VB 6.0中不同。在VB 6.0中,读写属性使用各自的属性过程。相比而言,现在的形式更紧凑,更便于阅读。
只读属性
有的属性值可以由其他基本属性值获得,是只读的,称为只读属性。在VB.NET和VC#.NET中,在属性过程中添加 ReadOnly关键字,并且只实现Get块,可以实现只读属性。例如,假设坐标原点为(0,0),则在同一坐标系中,当前点到原点的距离可以求得,把它设置为Disto属性,编码为:
【VB.NET】
Public ReadOnly Property Disto() As Double
Get
Return text-blue-400">Sqrt(m_x * m_x+m_y * m_y)
End Get
End Property"
【VC#.NET】
public float Disto
{
get{return(float)(Math.Sqrt(m_x*m_x+m_y*m_y));}
}
2. 只写属性
与只读属性相对应,有的属性是只写的。在属性过程中添加WriteOnly关键字,并且只实现Set块,可以实现只写属性。
3. 缺省属性
如果是用VB.NET编程,用Default关键字来标示属性时该属性定义为缺省属性。现在假设创建了一个CPoints类,它能够保存CPosition对象并能实现索引和删除。为了实现索引,定义了一个Item属性,它是一个缺省的只读属性,其中alD为索引值。该方法返回一个CPosition对象。
【VB.NET】
Default Public ReadOnly Property Item(ByVal aID As Integer) As Position
Get
'返回一个CPosition类型的对象
End Get
End Property
如果用VC#.NET 编程,要定义缺省属性则需要使用索引器,如下所示:
【VC#.NET】
public Position this {int aID}{
get{
//返回一个CPosition类型的对象
}
}
将属性定义为缺省属性以后,可以在类实例名称后面直接跟括号和索引值。例如,现在clines是一个CLines类实例,其中存储了10个CLine对象,则可以通过clines(4)的方式直接调用其中的第5个对象。
方法
方法是一些函数和过程。根据需要,可以创建公共方法、受保护的方法和私有方法等,它们具有不同的使用范围。
1. 公共方法
公共方法用Public或pu blic关键字进行标示,在整个项目范围内都可以使用。下面给Position类添加一个GetAngle方法,它返回当前点与坐标原点间的方位角。
【VB.NET】
Public Function GetAngle(ByVal p1 As PointF) As Single
'…
End Function
【VC#NET】
public float GetAngle(PointF p1){
//…
}
2. 受保护的方法
受保护的方法用Protected或protected关键字进行标示,可以用于本类及其派生类。受保护的方法就像那些只在特定系统或部门内适用的法规、规则一样。
3. 私有方法
在函数或过程前添加Pivate关键字,将方法设置为私有。私有方法只能被六类中的函数或过程所调用,是为其他函数服务的。比如,在交互绘制圆弧的过程中,拾取圆弧时需要知道拾取点是否落在圆弧所在的范围内,可通过比较拾取点、圆弧起点和终点这三点的方位角的关系来实现。此时,就要用到前面的GetAngle函数,它在这里是私有的。因为在外部调用圆弧类CArc的方法时不会用到它,它是为Pick方法服务的。可用下面的代码将方法设置为私有。
【VB.NET】
Public Class Carc
'…
Public Function Pick(Byval aPos As PointF,
Byval PickRadius As Single)
As Boolean
'…
angBegin=GetAngle(m_Begin)
angEnd=GetAngle(m_End)
angCur=GetAngle(aPos)
'…
End Function
Private Function GetAngle(Byval aPos As PointF) As Single
'…
End Function
'…
End Class"
【VC#.NET】
public class CArc
{
//…
public bool Pick(PointF aPos,float PickRadius)
{
//…
angBegin=GetAngle(m_Begin);
angEnd=GetAngle(m_End);
angCur=GetAngle(aPos);
//…
}
private float GetAngle(PointF aPos)
{
//…
}
}
构造函数
构造函数是VB.NET新增的功能,VB6.0里面没有。它的主要作用是提供对象数据的初始化。可以提供一个构造函数,也可以提供多个构造函数。
1. 创建无参构造函数
无参构造函数没有参数,每个类都有一个无参构造函数。下面给前面创建的CPositon类添加无参构造函数。用VC#.NET创建类时,会自动给出一个无参构造函数。
【VB.NET】
Public Sub New()
End Sub
【VC#.NET】
public position(){
}
2. 带参构造函数
构造困数可以带一个或多个参数。一般而言,类中应该提供尽可能全面的构造要 。下面给Position类提供两个构造函数,一个用给定的横、纵坐标定义,另一个用已经存在的点来定义。
【VB.NET】
Public Sub New(By Val xx As Single, By Val yy As Single)
m_x=XX
m_y =yy
End Sub
Public Sub New(ByVal aPos As Position)
With aPos
m x=.x
m y=.y
End With
End Sub
【VC#.NET]
public Position(float xx,float yy)
{
m_x=xx;
m_y=yy;
}
public Position(Position aPos)
{
m_x=aPos.x;
m_y =aPos.y;
}
重载
重载允许我们使用参数不同但名称相同的方法。假如前面定义了多个构造函数,过程名称都相同,但参数个数或类型不同,这实际上也是一种重载。在VB6.0里面不能实现重载,同一个类中不允许有名称相同的方法。
使用重载时可以有几种情况,一种是参数个数不相同,另一种是参数个数相同,但参数类型不全相同。为了演示重载,下面给Position类添加一组重载方法Move。第1个Move方法使当前点水平移动,第2个Move方法使当前点可以向平面上任何方向移动。
【VB.NET】
Public Sub Move(ByVal deltaX As Single)
m_x+=deltax
End Sub
Public Sub Move(ByVal deltaX As Single, ByVal deltaY As Single)
m x+=deltaX
m_y+=deltaY
End Sub"
【VC#.NET】
public void Move(float deltaX)
{
m_x+=deltaX;
}
public void Move(float deltaX, float deltaY)
{
m x+=deltaX;
m_y+=deltaY;
}
定义重载方法以后,调用时会显示黄色提示信息框。信息框中,前面是一个上下框,其中给出了重载方法的总个数和当前方法的序号;后面显示的是当前方法的调用格式。单击上下框两侧的箭头按钮,可以进行滚动,显示上一个或下一个方法的调用格式。
Me和this
在VB.NET和VC#.NET中,分别用Me和this调用自身成员。下面在两种语言的Position类中分别添加MeTest方法和 thisTest方法,在输出窗口输出当前点的坐标。
【VB.NET】
Public Sub MeTest()
text-blue-400">Console.text-blue-400">WriteLine("坐标为:{0),{1)", Me.x, Me.y)
End Sub
【VC#.NET】
public void thisTest()
{
Console.WriteLine("坐标为:[0),{1)", this.x, this.y);
}
应用Position类
为了说明类的创建,前面定义了一个Position类,包括它的属性、方法和构造函数等。下面对它进行测试,说明如何调用它的成员。在项目的Form1类中添加Form1 Load事件代码,在载入窗体时创建3个Position对象,然后在输出窗口中输出它们的坐标值。后面还测试了GetAngle方法和重载方法Move。
【VB.NET】
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal text-blue-400">e As System.EventArgs) Handles MyBase.Load
Dim aPos1 As New Position(10, 10)
Dim aPos2 As New Position(0, 0)
Dim aPos3 As New Position(aPos1)
text-blue-400">Console.text-blue-400">WriteLine("坐标为:{0},{1}",aPos2.x,aPos2.y)
text-blue-400">Console.text-blue-400">WriteLine("坐标为:{0},{1}",aPos3.x, aPos3.y)
text-blue-400">Console.text-blue-400">WriteLine(aPos1.GetAngle0)
aPos2.Move(100)
aPos3.Move(100,100)
text-blue-400">Console.text-blue-400">WriteLine("坐标为:{0},{1}",aPos2.x,aPos2.y)
text-blue-400">Console.text-blue-400">WriteLine("坐标为:{0},{1}", aPos3.x,aPos3.y)
aPos1.MeTestO
End Sub
(VC#.NET】
private void Forml_Load(object sender, System.EventArgs e)
{
Position aPos1=new Position(10, 10);
Position aPos2=new Position(0, 0);
Position aPos3=new Position(aPos1);
Console.WriteLine("坐标为:{0},{1}",aPos2.x,aPos2.y);
Console.WriteLine("坐标为:{0},{1}",aPos3.x,aPos3.y);
Console. WriteLine(aPos1.GetAngle());
aPos2.Move(100);
aPos3.Move(100,100);
Console.WriteLine("坐标为:{0},{1}",aPos2.x,aPos2.y);
Console.WriteLine("坐标为:{0},{1}",aPos3.x,aPos3.y);
aPos1.thisTest();
}