先看一个C++简单的日期类定义:
class TDate{ public: void SetDate(int y,int m,int d); int IsLeapYear(); void Print(); private: int year,month,day; };
C++类有:封装、继承、多态, VB没有继承
VB中可设置或取得的值称:字段或属性
区别:实现方式不同,属性是用一个过程来实现,这样就可以完成复杂的动作。
上面year相当于字段,SetDate()相当于属性
有时字段通过属性来进行访问,注意下面的简单类例。
通过类模块的方法来创建每一个类。类只含代码,没有GUI(界面)
类模块只有两个事件:Initialize Terminate
在每一个类中显式地用Option Explicite指明变量必须 显式声明是一个好习惯,并对每一个类名用cls或C来指明这是一个类的名字(就是类模块的名称)。
dim wakeUp as New CTime1
创建一个Ctime1类,三个实例变量mHour,mMinute,mSecond声明为Private,表示只能被类内进行访问。
(一般数据声明为Private,方法声明为Public,但这不是绝对的,比如前面的字段有时要外部访问时,就可声明为Public,只不过这样有风险,所以一般不这样做)
可以看到不是随便数据可以来设置分钟的,【0,59】是一个范围,如果用字段来设置就容易超范围而出错,用属性就可进行判断达到修正提示的作用。
在工程资源管事器内部右击,添加类模块,选中它,在下面属性中就可重命名为CTime1
SetTime(设置时间) ToUniversalTime(世界时) ToStandandTime(标准时)
类模块中代码:
Option Explicit Private mHour As Integer '类模块内可访问,类模块外不可访问 Private mMinute As Integer Private mSecond As Integer Public Sub SetTime(ByVal h As Integer,ByVal m As Integer,ByVal s As Integer) '类外亦可访问 mHour = IIf(h >= 0 And h < 24,h,0) mMinute = IIf(m >= 0 And m < 60,m,0) mSecond = IIf(s >= 0 And s < 60,s,0) End Sub Public Function ToUniversalTime() As String ToUniversalTime = Format(mHour,"00") & ":" & Format(mMinute,"00") & ":" & Format(mSecond,"00") End Function Public Function ToStandardTime() As String Dim h As Integer h = IIf(mHour = 12 Or mHour = 0,12,mHour Mod 12) ToStandardTime = h & ":" & Format(mMinute,"00") & " " & IIf(mHour < 12,"AM","PM") End Function
在窗体上添加一command1,双击打开代码窗,添加:
Option Explicit Private Sub Command1_Click() Dim t As New Ctime1 Print t.ToStandardTime Print t.ToUniversalTime Print Call t.SetTime(17,28,46) Print t.ToStandardTime Print t.ToUniversalTime Print Call t.SetTime(21,33,90) Print t.ToUniversalTime End Sub
按F5运行,即可显示相关时间
由上面例子可以看出:
1、类模块中最好用Option Explicit来显式地来声明每一个成员,这样避免不必要的错误。
2、Pivate仅类模块内访问,Pulbic还可在类模块外被访问,相当于是全局的。
同时把Private和Public分别进行集中放置,是一个好的习惯,这样查找修改更方便
3、Private在类外的实例中,不能访问,这就是封装。注意,const a as integer常量只能用Private
4、注意默认值,省略访问说明时,property,sub,function等默认为Public,实例变量默认为Private。
桥的作用
对于设置了Private的数据,又要想访问怎么办?正如C++一样,添加一个成员函数,这个成员函数Public的,它对类内可以访问Pivate数据,对类外又可被实例访问。
这样就架起了一桥,可以访问私有的数据,同时把一些判断语句加进来,使得更加合理。
在VB中这个桥有专门的语句:Property Get, Property Let, Property Set,它们在私有数据与实例对象中架起这个桥。
Property Get 取得数据
Property Set 设置数据,数据是对象时
Property Let 设置数据,数据是基本数据类型时(如上面例子的,mHour,mSecond等)
为什么要有获取和设置?这是因为应用的不同,有时要设置,有时要取出应用,如果某一个不应用的话,那只能单独地被设置或取出。
假定对mHour小时进行获取和设置:
Public Property Let hour(ByVal hr As Integer) '设置值,无须有返回值 mHour = IIf(hr >= 0 And hr < 24,hr,0) End Property Public Property Get hour() As Integer '取出,有返回值,这个返回值一般将赋值给另一个变量 hour = mHour End Property
于下有了下面应用情况:
dim t as CTime1,x as integer
t.hour=23 ' 这是设置值,故必须有Property Set Hour的定义
x=t.hour ' 这是取出值,故必须要有Property Get Hour的定义
所在,在只允许读的属性中时,不会对Property Let(Set)进行属性定义,或者虽然定义,但用Private限制访问
在类中属性的设置或获取中可以用 Exit Property 退出过程
通过Property过程,可以把原本Private的数据,变相地变成了Public访问。这就是桥的妙用。
New的作用
New只能用在对象中,当指定一个对象类型并用New时,就会在内存中分配一块,相当于对象的“框架”(构造函数)
如果只是说明对象,而没有用New的话,相当于是一个Nothing,什么也不是,如果引用它会产生错误,必须再用Set来设置其值
dim t as CTime1 ' 没有用New,它是一个nothing
x=t.hour ' 错误,nothing的对象是不是有值的
Set t=New Ctime1 ' 这是在声明对象类型后,再用Set进行赋值,然后用 x=t.hour才会有值。
类的合成
一个类中再次利用前面已经定义的另一个类,这种就叫类的合成,或者有些称为类的组合、包含。
实际上这个前面已经定义的类,可以把它当作基础类型一样对待就行了,它没啥了不起,脱了衣服还是一个类型同基础类型一样。