MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Visual Basic类与对象创建及实例化

2022-01-082.4k 阅读

Visual Basic 类的定义基础

类定义的语法结构

在 Visual Basic 中,类是一种用户自定义的数据类型,它封装了数据(字段和属性)和对数据进行操作的过程(方法)。定义一个类使用 Class 关键字,以下是一个简单的类定义结构示例:

Class MyClass
    '字段(成员变量)
    Private myField As Integer
    '属性
    Public Property MyProperty As Integer
        Get
            Return myField
        End Get
        Set(value As Integer)
            myField = value
        End Set
    End Property
    '方法
    Public Sub MyMethod()
        Console.WriteLine("This is MyMethod in MyClass.")
    End Sub
End Class

在上述代码中,MyClass 是类的名称。myField 是一个私有字段,只能在类内部访问。MyProperty 是一个公共属性,提供了对私有字段 myField 的受控访问。MyMethod 是一个公共方法,可从类的外部调用。

访问修饰符

  1. Private:使用 Private 修饰的成员(字段、属性、方法)只能在类的内部访问。例如上述代码中的 myField,外部代码无法直接访问它,这保证了数据的安全性和封装性。
  2. PublicPublic 修饰的成员可以从类的外部访问。像 MyPropertyMyMethod,其他代码可以创建 MyClass 的实例并访问这些公共成员。
  3. FriendFriend 修饰的成员在同一程序集内可以访问,但在程序集外部无法访问。这在大型项目中,当你希望某些类成员对同一项目中的其他代码可见,但对外部引用该程序集的代码不可见时非常有用。

类的成员详解

字段(成员变量)

  1. 定义与初始化:字段是类中声明的变量,用于存储类的状态信息。它们可以在声明时直接初始化,例如:
Class AnotherClass
    Private count As Integer = 0
    Private message As String = "Initial message"
End Class
  1. 作用域:字段的作用域取决于其访问修饰符。私有字段只能在类内部访问,而公共字段可以从类的外部访问。不过,通常建议将字段设为私有,并通过属性提供访问,以实现更好的数据封装。

属性

  1. 属性的作用:属性提供了一种灵活的方式来访问和修改类的字段。它们可以包含自定义的逻辑,例如验证输入值。属性可以分为只读属性(只有 Get 访问器)、只写属性(只有 Set 访问器)和读写属性(同时有 GetSet 访问器)。
  2. 只读属性示例
Class Circle
    Private radius As Double
    Public Sub New(ByVal r As Double)
        radius = r
    End Sub
    Public ReadOnly Property Area As Double
        Get
            Return Math.PI * radius * radius
        End Get
    End Property
End Class

在上述 Circle 类中,Area 属性是只读的,它根据 radius 字段计算圆的面积,外部代码只能获取该属性值,不能修改。 3. 只写属性示例:虽然只写属性不常见,但在某些场景下有用,例如在数据验证后只设置值而不允许读取。

Class PasswordClass
    Private password As String
    Public WriteOnly Property UserPassword As String
        Set(value As String)
            If value.Length >= 8 Then
                password = value
            Else
                Throw New ArgumentException("Password must be at least 8 characters long.")
            End If
        End Set
    End Property
End Class

这里的 UserPassword 属性是只写的,它验证输入的密码长度是否符合要求,符合则设置 password 字段。

方法

  1. 方法的定义与调用:方法是类中定义的过程,用于执行特定的操作。方法可以接受参数,也可以返回值。以下是一个简单的加法方法示例:
Class MathOperations
    Public Function Add(ByVal num1 As Integer, ByVal num2 As Integer) As Integer
        Return num1 + num2
    End Function
End Class

要调用这个方法,可以这样写:

Dim mathObj As New MathOperations()
Dim result As Integer = mathObj.Add(3, 5)
Console.WriteLine("The result of addition is: " & result)
  1. 方法重载:在同一个类中,可以定义多个同名但参数列表不同的方法,这就是方法重载。例如:
Class Calculator
    Public Function Add(ByVal num1 As Integer, ByVal num2 As Integer) As Integer
        Return num1 + num2
    End Function
    Public Function Add(ByVal num1 As Double, ByVal num2 As Double) As Double
        Return num1 + num2
    End Function
End Class

这里 Calculator 类有两个 Add 方法,一个接受两个 Integer 类型参数,另一个接受两个 Double 类型参数。编译器会根据调用时传入的参数类型来决定调用哪个方法。

构造函数与析构函数

构造函数

  1. 构造函数的作用:构造函数是类中的特殊方法,用于在创建类的实例时初始化对象的状态。在 Visual Basic 中,构造函数名为 New
  2. 默认构造函数:如果类中没有显式定义构造函数,Visual Basic 会提供一个默认的无参数构造函数。这个默认构造函数会将所有字段初始化为其默认值(数值类型为 0,字符串类型为 Nothing 等)。
  3. 自定义构造函数:当需要对对象进行特定的初始化时,就需要定义自定义构造函数。例如:
Class Person
    Private name As String
    Private age As Integer
    Public Sub New(ByVal pName As String, ByVal pAge As Integer)
        name = pName
        age = pAge
    End Sub
    Public Sub DisplayInfo()
        Console.WriteLine("Name: " & name & ", Age: " & age)
    End Sub
End Class

要创建 Person 类的实例并初始化其属性,可以这样做:

Dim person1 As New Person("John", 30)
person1.DisplayInfo()

析构函数

  1. 析构函数的作用:析构函数在对象被垃圾回收器回收之前执行清理操作,例如释放非托管资源(如文件句柄、数据库连接等)。在 Visual Basic 中,析构函数名为 Finalize
  2. 示例
Class ResourceHolder
    Private fileHandle As Integer
    Public Sub New(ByVal filePath As String)
        fileHandle = File.OpenHandle(filePath)
    End Sub
    Protected Overrides Sub Finalize()
        File.CloseHandle(fileHandle)
        MyBase.Finalize()
    End Sub
End Class

在上述代码中,ResourceHolder 类在构造函数中打开一个文件并获取文件句柄,在析构函数 Finalize 中关闭文件句柄以释放资源。需要注意的是,垃圾回收的时机是不确定的,因此不能依赖析构函数来执行对时间敏感的清理操作。

对象的创建与实例化

使用 New 关键字创建对象

  1. 基本语法:在 Visual Basic 中,使用 New 关键字来创建类的实例。例如,对于前面定义的 MyClass 类,可以这样创建实例:
Dim myObject As New MyClass()

这行代码做了两件事:首先,它声明了一个名为 myObject 的变量,其类型为 MyClass;然后,使用 New 关键字创建了 MyClass 的一个实例,并将该实例的引用赋给 myObject 变量。 2. 创建对象并初始化属性:如果类有自定义构造函数,可以在创建对象时传入参数来初始化对象的属性。例如对于 Person 类:

Dim person2 As New Person("Jane", 25)

对象引用与内存管理

  1. 对象引用:当使用 New 关键字创建对象时,实际上是在内存中分配了一块空间来存储对象的数据,而变量只是持有对该对象的引用。例如:
Dim obj1 As New MyClass()
Dim obj2 As obj1

这里 obj1obj2 都引用了同一个 MyClass 实例。如果通过 obj2 修改对象的属性,obj1 所引用的对象也会反映出这些变化。 2. 内存管理:Visual Basic 使用垃圾回收机制来管理内存。当一个对象不再有任何引用指向它时,垃圾回收器会在适当的时候回收该对象所占用的内存。例如:

Dim tempObj As New MyClass()
tempObj = Nothing

这里将 tempObj 设置为 Nothing,表示不再引用 MyClass 的实例,垃圾回收器最终会回收该实例占用的内存。不过,对于需要手动释放的非托管资源,如前面提到的文件句柄,需要在析构函数或专门的清理方法中进行处理。

类的继承

继承的概念与语法

  1. 继承的概念:继承允许一个类(子类)从另一个类(父类)中获取成员(字段、属性、方法等)。子类可以继承父类的特性,并可以添加自己的新成员或重写父类的成员。这有助于代码的复用和创建层次化的类结构。
  2. 继承的语法:使用 Inherits 关键字来实现继承。例如:
Class Animal
    Public Property Name As String
    Public Sub MakeSound()
        Console.WriteLine("The animal makes a sound.")
    End Sub
End Class
Class Dog
    Inherits Animal
    Public Sub Bark()
        Console.WriteLine("The dog barks.")
    End Sub
End Class

在上述代码中,Dog 类继承自 Animal 类,因此 Dog 类拥有 Animal 类的 Name 属性和 MakeSound 方法,同时 Dog 类还添加了自己的 Bark 方法。

重写方法

  1. OverridableOverrides 关键字:如果父类中的方法允许子类重写,需要在父类方法定义中使用 Overridable 关键字。子类重写该方法时,使用 Overrides 关键字。例如:
Class Shape
    Public Overridable Function Area() As Double
        Return 0
    End Function
End Class
Class Circle
    Inherits Shape
    Private radius As Double
    Public Sub New(ByVal r As Double)
        radius = r
    End Sub
    Public Overrides Function Area() As Double
        Return Math.PI * radius * radius
    End Function
End Class

这里 Shape 类的 Area 方法被声明为 OverridableCircle 类继承自 Shape 类并重写了 Area 方法来计算圆的面积。

多态性

  1. 多态的概念:多态性是指不同类的对象对同一消息(方法调用)做出不同响应的能力。在 Visual Basic 中,通过继承和方法重写来实现多态性。例如:
Dim shapes() As Shape = {New Circle(5), New Shape()}
For Each shape In shapes
    Console.WriteLine("Area: " & shape.Area())
Next

在上述代码中,shapes 数组包含了 Circle 类和 Shape 类的实例。当调用 Area 方法时,会根据对象的实际类型来调用相应的 Area 方法实现,这就是多态性的体现。

接口与抽象类

接口

  1. 接口的定义:接口是一种特殊的抽象类型,它只定义方法、属性等成员的签名,而不包含实现。接口使用 Interface 关键字定义。例如:
Interface IPrintable
    Sub Print()
End Interface
Class Document
    Implements IPrintable
    Public Sub Print() Implements IPrintable.Print
        Console.WriteLine("Printing document...")
    End Sub
End Class

这里 IPrintable 接口定义了一个 Print 方法,Document 类实现了该接口,并提供了 Print 方法的具体实现。 2. 接口的作用:接口允许多个不相关的类实现相同的行为,从而实现更灵活的多态性。例如,不同类型的对象(如文档、图像等)都可以实现 IPrintable 接口,以便在需要打印的地方统一处理。

抽象类

  1. 抽象类的定义:抽象类是一种不能被实例化的类,它可以包含抽象方法(只有声明,没有实现)和非抽象方法。抽象类使用 MustInherit 关键字定义,抽象方法使用 MustOverride 关键字定义。例如:
MustInherit Class AbstractShape
    Public MustOverride Function Area() As Double
    Public Sub DisplayInfo()
        Console.WriteLine("This is an abstract shape.")
    End Sub
End Class
Class Rectangle
    Inherits AbstractShape
    Private width As Double
    Private height As Double
    Public Sub New(ByVal w As Double, ByVal h As Double)
        width = w
        height = h
    End Sub
    Public Overrides Function Area() As Double
        Return width * height
    End Function
End Class

这里 AbstractShape 是一个抽象类,它有一个抽象方法 Area 和一个非抽象方法 DisplayInfoRectangle 类继承自 AbstractShape 类,并实现了 Area 方法。 2. 抽象类与接口的区别:抽象类可以包含实现代码和成员变量,而接口只能包含成员的声明。一个类只能继承一个抽象类,但可以实现多个接口。抽象类适用于当存在一些共同的行为或状态需要在子类中共享时,而接口适用于当需要为不相关的类提供统一的行为定义时。

泛型类与对象

泛型类的定义

  1. 泛型的概念:泛型允许你创建可以与不同数据类型一起工作的类、方法等,而无需为每种数据类型创建单独的版本。这提高了代码的复用性和类型安全性。
  2. 泛型类的语法:定义泛型类时,在类名后面使用尖括号 <> 来指定类型参数。例如:
Class GenericList(Of T)
    Private items() As T
    Private count As Integer = 0
    Public Sub Add(ByVal item As T)
        If count = items.Length Then
            Array.Resize(items, count + 1)
        End If
        items(count) = item
        count += 1
    End Sub
    Public Function GetItem(ByVal index As Integer) As T
        If index < 0 Or index >= count Then
            Throw New IndexOutOfRangeException()
        End If
        Return items(index)
    End Function
End Class

这里 GenericList(Of T) 是一个泛型类,T 是类型参数。这个类可以用于存储任何类型的对象,并提供了添加和获取对象的方法。

使用泛型类创建对象

  1. 实例化泛型类:要使用泛型类,需要在实例化时指定实际的类型参数。例如:
Dim intList As New GenericList(Of Integer)()
intList.Add(10)
intList.Add(20)
Dim value As Integer = intList.GetItem(0)
Console.WriteLine("The value is: " & value)

这里创建了一个 GenericList(Of Integer) 的实例,用于存储 Integer 类型的数据。同样,也可以创建用于存储其他类型数据的实例,如 GenericList(Of String) 等。 2. 泛型类的优势:泛型类减少了代码的重复,同时在编译时提供了类型检查,提高了程序的安全性和性能。相比于使用 Object 类型来处理多种数据类型,泛型避免了装箱和拆箱操作,从而提高了效率。

总结 Visual Basic 类与对象相关要点

通过以上对 Visual Basic 类与对象创建及实例化的详细阐述,我们了解了类的定义、成员的种类、对象的创建与使用,以及继承、接口、抽象类和泛型等重要概念。这些知识构成了 Visual Basic 面向对象编程的核心内容,熟练掌握它们对于开发高质量、可维护和可扩展的应用程序至关重要。在实际编程中,要根据具体的需求和场景,合理运用这些特性,以实现最佳的编程效果。无论是开发小型的桌面应用程序,还是大型的企业级系统,对类与对象的深刻理解和灵活运用都将是成功的关键。在日常编码实践中,不断练习和尝试不同的面向对象设计模式,结合实际项目需求优化代码结构,能够进一步提升编程技能和解决复杂问题的能力。希望通过本文的学习,读者能够在 Visual Basic 的面向对象编程领域迈出坚实的步伐,创造出更加优秀的软件作品。