PS:除非特别声明,本文所说VB指的是VB6,而非VB.NET。 大家都知道,VB是一种半面向对象(也有人称之为“伪面向对象”)的语言,他虽然可以写自定义的类,但是由于种种原因,使得他在这方面的发育产生了一点问题,比如说:VB写出来的类是不能继承的(不孕不育?!-_-#...传说VB的偶像是东方不败……残念-_-#!),你无法像在C++/C#/JAVA==中一样自由的使用类。你很难想象类没有继承会有啥用途。还有,在VB中,一个类模块只能写一个类,这意味着如果你的Project中使用了N个类,你必须忍受它带着N个类模块文件,甚至其中有些只是小小小类。这些都造成VB的类的可用性和重用性不佳。 但是,VB是否在类的方面就这么无能呢?答案是否定的,在很多时候(特别是需要将很多功能封装,形成模块化的时候),VB 的自定义类还是能派上用场的。这里,有人可能会想到使用ActiveX控件,虽然在VB中,可以使用ActiveX控件做到上述功能,但是写ActiveX控件要比写类麻烦得多,而且ActiveX控件的资源占用也要比类大。当然,如果你只想去往上搜搜ActiveX控件,然后拼成一个程序的话,我完全可以对你说:“原谅我浪费了你的生命!” 那么接下来,我们就已Animal为主题讲讲在VB6中写自定义类的方法~ 成员函数和成员变量 首先,我们需要添加一个类模块,然后将它的名称改成Animal,那么,这个类的名字就是Animal。然后再写入下列代码: 引用:Private m_strName As String, m_bytLegs As Byte, m_blnBark As Boolean 然后,我们定义了几个成员函数,用它完成相应的功能。至于什么是成员函数(还有刚才提到的成员变量),这点大家可以不必了解,这其实是C++的叫法,只不过上校在VB中也习惯这么叫。这完全是称呼问题。大家可以看到,我把变量名写成m_XXX,这里的m_是成员变量的标记,用于和其他变量区分,这是典型的匈牙利命名法。 BTW:关于匈牙利命名法,大家可以去Google了解下。个人感觉匈牙利命名法在VB中实用性很强,所以我的声明习惯基本都符合匈牙利命名法。 然后我们看看后面的一些函数。他们都用Public声明,原因和前面声明成员变量类似,这里不再阐述。函数功能也都已注释,大家可以自己看。 类的使用方法 类写好了,我们要开始使用它。和使用其他数据类型一样,我们要先声明。但是有所不同的是,类的声明通常有两种方法: 两者相同之处在于都声明了一个名为cAnimal的对象变量,并用New将其实例化,这是使用自定义类所必需的。而两者的不同在于后者在声明Animal对象变量的时候就将其实例化,而前者则是先声明对象变量,再在适当的时候将其实例化。相比之下,前者可以控制实例化类的时间和场合,因此更为自由,普遍。 说完了声明我们先来讲讲类的销毁。每一个类的使用都要占用一定的资源,当不需要这些类时,需要释放他们所占用的资源,这是良好的Coding Habits~ 类的销毁比较简单,只需要 即可。 这里建议大家在声明完类之后,就马上在适当的地方写入销毁类的代码,避免因为遗忘而造成错误。 接下来,我们要开始使用我们的Animal类 引用:Private Sub Form_Load() 使用类实例和使用控件很像,当输入类名+. 即cAnimal.的时候,就会出现信息条 然后进行相应操作即可。 引用:Private Sub Form_Click() 类的属性 不知道大家有没有发现,无论我们是获取,还是设置Name/Legs/Bark的信息,都需要使用一个单独的成员函数。而我们在使用控件时,那些都是作为属性(Property)来实现的。所以,接下来,我们要研究如何在自定义类中实现属性。 为了方便之后对比,我们仅把Name转化为属性实现: 引用:Public Property Get Name() As String 这样,我们就可以像在控件中一样,直接使用Name这个属性来设置和获取相关信息。 BTW:如果你觉得编写属性过程太麻烦,可以使用工具菜单中的添加过程来减轻工作量 另外,我们可以通过只编写Let或者Get过程来生成只读/只写的属性 看到这里,不知道大家想过没有,既然Get/Let属性过程很像Function/Sub,而Function/Sub是可以有多个参数的,那么Get/Let属性是不是也可以有参数呢? 当然,这是可以的,只不过相当少见(我们平常在用控件属性时,MS都没遇到过),而且它还有着比较严格的规定和限制,如果你对这方面不感兴趣或者认为用不着,可以跳到后面去。 现在我们就额外添加一个Age的参数,看看如何在属性过程中使用多参数。 首先我们的属性过程要改为: 引用:Public Property Get Name(ByVal intAge As Integer) As String 我们可以通过一张图片来大致了解下Let过程的调用。 所以,相应的,我们对Name属性的代码也要更改如下: 运行后,立即窗口就会出现: 但是,当我们在使用Get过程时,那个参数并没有作用,却又必须存在。这时,我们可以将其声明为可选参数,这样,Get确有参数存在,我们也可以免去放入无用实参的麻烦。 虽然在属性过程中使用多个参数可以在一定程度上加快便捷,但是这是牺牲实用性为代价的。多个参数的过程属性在使用上非常不便,而且看起来不伦不类的。所以,上校建议如非真的必要,就不要使用多参数。 特殊的类属性 其实,在VB的Class里,还有一种很普通但不普遍的类属性——共有成员变量。 我们在之前强调过,一般情况下,成员变量应为私有,这是封装的要求。而如果成员变量的属性是共有的,则其在外部也可以被访问,这就形成了一个简单的类属性,属性名就是他的变量名。 和属性过程相比,公有成员变量不能设置为只读/只写,无法在更改自己的同时更改其他的属性值,也不能验证数据等。(因为修改共有变量属性仅是修改它的值,而通过属性过程,则可以进行一系列的操作)但是共有成员变量作为属性,能很大程度上减少代码量,简化操作。下面有一些使用类属性的原则,仅供参考: 引用:From:M$ MSDN 属性和成员函数的选择 在类编写中,经常会遇到选择属性还是成员函数实现的问题,就此,我们对属性和成员函数的选择给出自己的判断标准(仅供参考): 一般来说,属性是对某个对象本身特征的描述,属性是对向所拥有的,比如Name、Age、Height等等;而成员函数则用于执行对象的某种行为/动作,比如Move、Jump、Cook等。(此处是对于VB来说,CPP MS没有类似于VB属性过程的东西,所以成员函数也用于设置属性。) 不过,有时,就像人类行为也存在一个边界不清一样,可能上述的方法不管用。那么,你可以根据自身的要求和条件或者说癖好决定。 这里,还有最后一招,这招是上校的独门绝技,不仅在此处适用,而且在任何学科,任何情况下皆适用。最大的好处在于你会无条件的服从自己~这招就是~~铛~~铛~~铛~~掷——硬——币。 回声:)让我送你去见毛主席吧~-_-#! 构造函数与析构函数 当我们希望类在被初始化时,自动的执行一些操作。比如:为某个成员变量赋初始值。这时候,我们就需要构造函数。当然,这里的构造函数(和下文的析构函数)同样是CPP的叫法。 构造函数表示为: BTW:大家可以先在左上端的对象下拉框内选择Class,然后在右边选择Initialize 比方说,我们希望在类被初始化,m_strName自动被赋予“IceBear”,只需: 说完构造函数,咱再说说析构函数。 析构函数是类被销毁时要进行的操作,通常用于清理、释放等操作。他的函数名是: 析构函数的用法和构造函数相似,这里不再阐述。 缺憾 VB的类的缺陷是比较多的,就像我们刚开始了解的那样,他不能够继承,而且用类模块其实是一件挺烦的事。相对于其他OOP语言来说,VB的类还不支持真正的多态(VB是通过多重 ActiveX 接口来提供多态的),而友元效果也不太令人满意。 还有一点比较重要,就是在类模块中是不能使用子类化(SubClass)和钩子(Hook)的。(除非你会用ASM写一个处理子程,然后挂接) 尾声 至此,我们已经了解了VB类的大体使用方法,大家如果对此感兴趣的话,可以自己通过MSDN学习:事件(events)、友元(Friend:VB中是这样)等更高级的技术。 咳...咳...上校顺便插段AD: http://bbs./viewthrea ... p%3Bfilter%3Ddigest 这里是上校自己写的托盘图标类,大家有兴趣可以看看Source Code。 |
|