对象是可以视为单元的代码和数据的组合。 对象可以是应用程序(如控件或窗体)的一部分。 整个应用程序也可以是一个对象。
在 Visual Basic 中创建应用程序时,会不断处理对象。 可以使用 Visual Basic 提供的对象,例如控件、窗体和数据访问对象。 还可以在 Visual Basic 应用程序中使用来自其他应用程序的对象。 甚至可以创建自己的对象并为其定义其他属性和方法。 对象就像程序预制构建基块一样, 它们允许你编写一段代码,并反复重复使用它。
本主题详细讨论对象。
对象和类
Visual Basic 中的每个对象都由 类定义。 类描述对象的变量、属性、过程和事件。 对象是类的实例;定义类后,可以根据需要创建任意数量的对象。
若要了解对象与其类之间的关系,请考虑饼干切割机和饼干。 饼干切模是类。 它定义每个 Cookie 的特征,例如大小和形状。 该类用于创建对象。 这些对象是 Cookie。
必须先创建对象,然后才能访问其成员,但 Shared
成员除外,无需使用类的对象便可访问这些成员。
基于类创建对象
确定要使用哪个类来创建对象,或者定义您自己的类。 例如:
Public Class Customer Public Property AccountNumber As Integer End Class
编写 Dim 语句 以创建可向其分配类实例的变量。 变量应为所需类的类型。
Dim nextCustomer As Customer
添加 New Operator 关键字以将变量初始化为类的新实例。
Dim nextCustomer As New Customer
现在可以通过对象变量访问类的成员。
nextCustomer.AccountNumber = lastAccountNumber + 1
注释
应尽可能将变量声明为要分配给它的类类型。 这称为 早期绑定。 如果在编译时不知道类类型,可以通过声明变量为对象数据类型来调用后期绑定。 但是,后期绑定会使性能变慢,并限制对运行时对象成员的访问。 有关详细信息,请参阅 对象变量声明。
多个实例
从类中新建的对象通常彼此相同。 但是,一旦它们作为单个对象存在,可以独立于其他实例更改其变量和属性。 例如,如果将三个复选框添加到窗体,则每个复选框对象都是类的 CheckBox 实例。 各个 CheckBox 对象共享由类定义的一组常见特征和功能(属性、变量、过程和事件)。 不过,每个对象都有自己的名称,不仅可以分开启用和禁用,还可以位于窗体上的不同位置。
对象成员
对象是应用程序元素,表示类的 实例 。 字段、属性、方法和事件是对象的构建基块,构成其 成员。
成员访问
可以通过按顺序指定对象变量的名称、句点(.
和成员的名称)来访问对象的成员。 以下示例设置 Text 对象的属性 Label 。
warningLabel.Text = "Data not saved"
IntelliSense 列出成员
当你调用类的“列出成员”选项时(例如,将句点 (.
) 作为成员访问运算符键入时),IntelliSense 会列出类的成员。 如果在声明为相应类实例的变量名称后键入句点,IntelliSense 会列出所有实例成员,而不列出任何共享成员。 如果在类名本身后面键入句点,IntelliSense 会列出所有共享成员,而不列出任何实例成员。 有关详细信息,请参阅使用 IntelliSense。
字段和属性
字段 和 属性 表示存储在对象中的信息。 使用赋值语句检索和设置其值的方式与在过程中检索和设置局部变量的方式相同。 以下示例检索属性 Width 并设置 ForeColor 对象的属性 Label 。
Dim warningWidth As Integer = warningLabel.Width
warningLabel.ForeColor = System.Drawing.Color.Red
请注意,字段也称为 成员变量。
在以下情况下,使用属性过程:
你需要控制何时以及如何设置或检索值。
该属性具有一组定义完善的值,需要验证这些值。
设置该值会导致对象状态发生一些可感知的变化,例如
IsVisible
属性。设置属性会导致对其他内部变量或其他属性的值进行更改。
必须先执行一组步骤,然后才能设置或检索属性。
在以下情况下,使用字段:
该值为自验证类型。 例如,如果将除
True
或False
之外的值赋给Boolean
变量,则会发生错误或自动数据转换。数据类型支持的范围中的任何值都有效。 对于
Single
或Double
类型的许多属性,同样如此。该属性是一种
String
数据类型,对字符串的大小或值没有约束。有关详细信息,请参阅 属性过程。
小窍门
始终将非恒定字段设置为私有。 要使其成为公共字段,请改用属性。
方法
方法是对象可以执行的动作。 例如,Add 是 ComboBox 对象的一个方法,用于向组合框添加新条目。
Dim safetyTimer As New System.Windows.Forms.Timer
safetyTimer.Start()
请注意,方法只是由对象提供的过程。
有关详细信息,请参阅 过程。
事件
事件是对象识别的动作,例如单击鼠标或按键,你可以编写代码来响应。 事件可能是用户作或程序代码造成的,也可能是由系统引起的。 表示事件信号的代码据说 引发 事件,响应事件的代码据说 用于处理 事件。
还可以开发自己的自定义事件,以便由对象引发,并由其他对象处理。 有关详细信息,请参阅 事件。
实例成员和共享成员
从类创建对象时,结果是该类的实例。 未使用 Shared 关键字声明的成员是属于该特定实例的 实例成员。 一个实例中的实例成员独立于同一类的另一个实例中的同一成员。 例如,实例成员变量在不同实例中可以具有不同的值。
使用 Shared
关键字声明的成员是属于整个类的 共享成员,不属于任何特定实例。 无论创建多少类实例,或者即便未创建实例,共享成员也都只有一个。 例如,共享成员变量只有一个值,可用于可访问该类的所有代码。
访问非共享成员
确保对象已从其类创建并分配给对象变量。
Dim secondForm As New System.Windows.Forms.Form
在访问成员的语句中,请在对象变量名称后使用 成员访问运算符(
.
),然后是成员名称。secondForm.Show()
访问共享成员
在类名之后使用成员访问运算符(
.
),然后是成员名称。 应始终通过类名直接访问Shared
对象的成员。Console.WriteLine("This computer is called " & Environment.MachineName)
如果已从类创建对象,则可以通过对象的变量访问
Shared
成员。
类和模块之间的差异
类和模块之间的主要区别在于,类可以实例化为对象,而标准模块则不能。 由于标准模块的数据只有一个副本,因此当程序的一部分在标准模块中更改公共变量时,如果程序的任何其他部分读取该变量,则获取相同的值。 相反,每个实例化的对象都有各自的对象数据。 另一个区别是,与标准模块不同,类可以实现接口。 如果类使用 MustInherit 修饰符进行标记,则无法直接实例化该类。 但是,它仍然不同于模块,因为它可以继承,而模块不能继承。
注释
Shared
当修饰符应用于类成员时,它与类本身(而不是类的特定实例)相关联。 该成员是使用类名直接访问的,与访问模块成员的方式相同。
类和模块也对其成员使用不同的作用域。 类中定义的成员在类的特定实例范围内,并且仅在对象的生存期内存在。 若要从类外部访问类成员,必须使用 对象格式的完全限定名称。成员。
另一方面,默认情况下,模块中声明的成员是公开访问的,并且可由可访问模块的任何代码访问。 这意味着标准模块中的变量实际上是全局变量,因为它们在项目中的任意位置可见,并且它们存在于程序的生命周期中。
重用类和对象
对象允许声明变量和过程一次,然后在需要时重复使用它们。 例如,如果要向应用程序添加拼写检查器,则可以定义所有变量和支持函数以提供拼写检查功能。 如果将拼写检查器创建为类,则可以通过添加对已编译程序集的引用在其他应用程序中重复使用它。 更好的是,可以使用别人已经开发的拼写检查类,从而减少自己的工作量。
.NET 提供了许多可供使用的组件示例。 以下示例使用 TimeZone 命名空间中的 System 类。 TimeZone 提供的成员可检索当前计算机系统的时区信息。
Public Sub ExamineTimeZone()
Dim tz As System.TimeZone = System.TimeZone.CurrentTimeZone
Dim s As String = "Current time zone is "
s &= CStr(tz.GetUtcOffset(Now).Hours) & " hours and "
s &= CStr(tz.GetUtcOffset(Now).Minutes) & " minutes "
s &= "different from UTC (coordinated universal time)"
s &= vbCrLf & "and is currently "
If tz.IsDaylightSavingTime(Now) = False Then s &= "not "
s &= "on ""summer time""."
Console.WriteLine(s)
End Sub
在前面的示例中,第一个 Dim 语句 声明一个类型 TimeZone 的对象变量,并将一个由 TimeZone 属性返回的 CurrentTimeZone 对象赋给该变量。
对象之间的关系
对象可以通过多种方式相互关联。 关系的主要类型为 分层 和 包含。
分层关系
当类派生自更基础类时,它们据说具有 分层关系。 类层次结构在描述属于更常规类的子类型的项时非常有用。
在下面的示例中,假设你想定义一种特殊类型的Button,它的行为类似于普通的Button,但也具有一种反转前景和背景颜色的方法。
定义一个从现有类派生的类。
使用 Class 语句 定义从中创建所需对象的类。
Public Class ReversibleButton
请确保
End Class
语句遵循类中的最后一行代码。 默认情况下,集成开发环境(IDE)会在输入End Class
语句时自动生成Class
。在
Class
语句后面紧接着编写 Inherits 语句。 指定新类派生自的类。Inherits System.Windows.Forms.Button
新类继承基类定义的所有成员。
添加派生类公开的其他成员的代码。 例如,可以添加方法
ReverseColors
,并且派生类可能如下所示:Public Class ReversibleButton Inherits System.Windows.Forms.Button Public Sub ReverseColors() Dim saveColor As System.Drawing.Color = Me.BackColor Me.BackColor = Me.ForeColor Me.ForeColor = saveColor End Sub End Class
如果从
ReversibleButton
类创建对象,则它可以访问该类的所有成员 Button ,以及ReverseColors
方法以及在其中ReversibleButton
定义的任何其他新成员。
子类从它们所基于的类继承成员,使你可以随着类层次结构的推进增加复杂性。 有关详细信息,请参阅 继承基础知识。
编译代码
请确保编译器可以访问要从中派生新类的类。 这可能意味着完全限定其名称,如前面的示例所示,或在 Imports 语句(.NET 命名空间和类型)中标识其命名空间。 如果类位于其他项目中,则可能需要添加对该项目的引用。 有关详细信息,请参阅 管理项目中的引用。
包含关系
对象之间可以建立的一种关系是 包含关系。 容器对象在逻辑上封装其他对象。 例如,该 OperatingSystem 对象在逻辑上包含一个 Version 对象,该对象通过其 Version 属性返回。 请注意,容器对象在物理上不包含任何其他对象。
收集
一种特定类型的对象包含由 集合表示。 集合是可以枚举的类似对象的组。 Visual Basic 支持 For Each 中的特定语法 ...下一个语句 ,用于循环访问集合的项。 此外,集合通常允许你通过 Item[] 索引或将它们与唯一字符串相关联来检索元素。 集合比数组更易于使用,因为它们允许添加或删除不使用索引的项。 由于它们的易用性,集合通常用于存储窗体和控件。
相关主题
演练:定义类
提供有关如何创建类的分步说明。
重载属性和方法
重载属性和方法
继承基础知识
介绍了继承修饰符、重写方法和属性(MyClass 和 MyBase)。
对象生存期:如何创建和销毁对象
讨论如何创建和销毁类实例。
匿名类型
介绍如何创建和使用匿名类型,这样就可以在不编写数据类型的类定义的情况下创建对象。
对象初始值设定项:命名类型和匿名类型
探讨使用单个表达式创建命名类型和匿名类型实例的对象初始值设定项。
如何:推断匿名类型声明中的属性名称和类型
介绍如何在匿名类型声明中推断属性名称和类型。 提供成功和失败推理的示例。