我在以前的文章里曾经提到:VB.NET的出现使得VB6在类的概念及其操作上发生了巨大的变化。现在就让我们进到这些变化中来进行更深入的探讨。首先让我们看看类到底意味着什么。
不妨假设我把你带回到了学院,现在你走进一个教室,我要求你解释一下什么是类(class),你可能会这样回答:“一组学生形成一个班(class)。”呵呵,如果这样回答,你真是歪打正着了:没错,在这里,组就是最关键的词。用面向对象的编程思想来看,类就是存储数据同时给一组相关代码赋予协调功能的方式。类是面向对象编程的核心。
.NET赋予类的新面目
VB6和VB.NET在类的用法上有一个首要的显著差别,那就是后者不再采用Set关键词了。除此以外,在代码中定义类的方法也有所改变。这些变动不仅会直接影响你编写的代码而且更会改变你组织源文件的方式。
在VB6下,每个类都必须在单个源文件内增加和定义。而在VB.NET下就不是这样了:类以代码块的形式定义,如下所示:
Public Class MyClass
'在这里编写类的成员代码!
End Class
面对如此革命性的变化,有些人可能会急得嘴角发泡,而大多数人却可能并不在乎或不明白用代码块定义类到底用什么用。说真的,这全看你的口味。有些人喜欢而且希望一个文件中就只定义一个类,而另一些人则更愿意逻辑地组织他们的类。例如,如果你有一个product类,同时又有了一个对应的products collection类,那么你完全可以把它们放在同一文件里以便更好地组织源文件。
类的构造和析构——旧貌换新颜
当你的代码在创建一个类的实例时会调用该类的一个特殊方法:构造器(constructor)。同样的,在类被破坏的时候则会调用析构器(destructor)方法。在大多数面向对象语言里牵扯到类的构造和析构时通常都采用了以上两个一般术语而非具体编码时的成员名。我则喜欢采用术语“structors”来引用构造和析构。在VB6语言里,具体的“structors”是Class_Initialize和Class_Terminate。在VB.NET下,Class_Initialize方法则被重命名为New,而Class_Terminate则成了Finalize。
按照VB6对类构造器的实现限制,程序员不得给该方法添加参数。然而,VB.NET中则对构造器方法提供了参数支持。在VB.NET下,你现在可以随意地把参数添加到这个方法中来,甚至可以重载该方法。
参数化的构造器如何灵活地创建类呢?举个例子,假设有一个ADO Connection类。用VB6语言的话,你首先得把该类实例化,然后在代码中用ConnectionString属性定义连接。要用VB.NET的话,这个类的构造器就被参数化和重载了,这样,在程序员给对象实例化时就可以给它传递一个连接字符串,这样你就不必关心代码内如何设置以后的连接了。当然,你完全可以按老办法做:什么参数都不传递,以后在代码中设置连接字符串。
域和属性
很多人在对属性的认识上产生了一些混乱的概念。其实属性这个东西绝非人们想象的那么复杂。让我们回到最基础的概念层次上来讨论属性:所谓属性其实就是暴露了读/写接口的类的内部所包含的一块数据。按照这个定义,你可能会认为你能在类中声明一个公共变量然后把它称为一个属性。当然,这种假设也不是没有一点道理,不过,类的公共变量所对应的技术术语应该是field(域)。域和属性之间的关键差别在于接口的包含性质上。现在暂时不对这一差别做具体解释咱们先明白其语法用途即可。
在VB6中,属性由Let、Get和Set程序来定义和操作。而在VB.NET中语法就变了。属性被组织为单个Property代码块,其中针对属性的写(Set)和读(Get)操作设置了子代码块。这一程序起到了类的私有变量之上的抽象层作用。大多数人习惯于采用类似公共变量的方式命名这些私有变量,在它们前面加上小写的前缀字母m或者加上下划线区分所关联的属性(m前缀是VB6中继承下来的,意思是:“模块级变量”)。举一个例子:
Private _ContactName As String
Public Property ContactName()
Get
Return _ContactName
End Get
Set(ByVal Value)
_ContactName = Value
End Set
End Property
我给一个假定的类ContactName创建了一个属性。为了支持该属性,我需要在类里设置一个变量存储其实际值。ContactName私有变量就是完成这一功能的。只要我获取或者设置了该属性,我就等于间接地使用了该值。
那么,为什么这么做就比使用域更好一些呢?主要的原因是,如果采用域,那么就无法控制写到变量中的数据。比方说,有的人却偏偏要在整数域中置入字符串或者给只读域赋值。在采用属性的情况下,你可以在Set程序中增加逻辑来保证赋值的有效性。你甚至可以完全省略Set代码块把属性设置为只读。
属性真奇妙
最后,.NET还向我们提供了就被称为属性的内容。如果某个类标记为属性,那么它就被赋予一些特别有意思的专门功能。比如以下的Serializable属性。
<Serializable()>
Public Class MyClass
'该类可以串行化!
End Class
把以上的类标记为属性之后,不论其处于什么状态我都可以获取其实例并写出磁盘。在一些任何时候,我就可以对该类去串行化,就好象它始终保存在内存中一样。.NET框架提供了大量的属性,你甚至可以自己用VB.NET创建属性。
继承
正如你看到的那样,VB.NET的类在概念和工作方式上相比VB6.0已经发生了重要的变化。在下一篇文章里,我还会继续对这些变化进行讨论,主要是阐述类的继承问题。大多数VB程序员都可能了解继承,但他们却几乎从来没有使用过它。我将具体解释下继承的重要性以及在什么情况下采用继承