Class 包含其他对象数组的对象

Class Object containing an array of other objects

我用多种语言编写过程序,但我在 VBA 上进行第一次测试。

我需要制作一个 class 作为 属性,另一个 class 的对象数组。 让我们举一个例子,一个 Person class 保存关于名字、姓氏和地址的信息。还有一个保存有关街道和邮政编码信息的地址 class。一个人可以有很多地址,所以 Person 应该有一个地址数组。

class Address
Private pStreet as String
Private pZip as Int

Public Property Let Street(val As String)
    pStreet = val
End Property
Public Property Get Street() As String
    Street = pStreet
End Property
Public Property Let Zip(val As String)
    pZip = val
End Property
Public Property Get Zip() As String
    Zip = pZip
End Property
class Person
Private pName as String
Private pSurname as String
Private pAddresses() as Address

Public Property Let Name(val As String)
    pName = val
End Property
Public Property Get Name() As String
    Name = pName
End Property

Public Property Let Surname(val As String)
    pSurname = val
End Property
Public Property Get Surname() As String
    Surame = pSurname
End Property

我应该如何管理地址数组?

我试过这样的代码,但是如果我尝试在一个人对象上调用这个方法,我会得到一个错误“对象不支持这个 属性 或方法”

Public Sub addAddress(val as Address)
    ReDim pAddresses(1)
    pAddresses(0) = val
End Sub

有什么方法可以做到这一点?我找不到任何教程或任何展示如何在对象内部使用对象数组的东西

将您的代码更改为这样应该可以工作

 Public Sub main()
        
    Dim val As New Address
    val.Street = "MyStreet"
    val.Zip = 666
    Dim val2 As New Address
    val2.Street = "my New Street"
    val2.Zip = 999
    
    
    Dim myself As New Person
    With myself
        .Name = "its Me"
        .Surname = "Smith"
        Call .addAddress(val)
        Call .addAddress(val2)
    End With
    
    
    ' Get Number off addresses available
    Debug.Print "Number of Adresses: " &   myself.GetAddresses.Count
    
    ' Read the Addresses
    Dim Add As Address
    For Each Add In myself.GetAddresses
        Debug.Print "Streetname: " & Add.Street & ", Zip:" & Add.Zip
    Next
    
    ' Get First Address of the List
    Debug.Print "First Adress - Streetname:  " & myself.GetAddresses(1).Street
    Debug.Print "First Adress - Zip:  " & myself.GetAddresses(1).Zip
        
    ' Get The Address Object itself
    Dim theAdd As Address
    Set theAdd = myself.GetAddresses(1)
    Debug.Print "First Adress - Streetname:  " & theAdd.Street
    Debug.Print "First Adress - Zip:  " & theAdd.Zip
    
    ' Remove Address
    Call myself.GetAddresses.Remove(1)
    
End Sub
        
            
            
                
 class Address
    Private pStreet As String
    Private pZip As Integer
    
    Public Property Let Street(val As String)
        pStreet = val
    End Property
    Public Property Get Street() As String
        Street = pStreet
    End Property
    Public Property Let Zip(val As String)
        pZip = val
    End Property
    Public Property Get Zip() As String
        Zip = pZip
    End Property
    
 end class

            
             
                
class person
                    
    Private pName As String
    Private pSurname As String
    Private pAddresses As Collection

    Private Sub Class_Initialize()
       Set pAddresses = New Collection
    End Sub
    
    Public Property Let Name(val As String)
        pName = val
    End Property
    Public Property Get Name() As String
        Name = pName
    End Property
    
    Public Property Let Surname(val As String)
        pSurname = val
    End Property
    Public Property Get Surname() As String
        Surame = pSurname
    End Property
    
    Public Sub addAddress(val As Address)
        Call pAddresses.Add(val)
    End Sub
    
    Public Function GetAddresses() As Collection
        Set GetAddresses = pAddresses
    End Function
    
end class

首先,使用 NEW 关键字创建 objects,然后 SET 将 objects 添加到变量。如果要在变量中存储对现有 object 的引用,则始终必须使用 SET 关键字。

通过 Person.GetAddresses() 函数显示对 Person class 地址 collection 的访问本身并不是一种干净的封装方式。但我认为这有助于更好地理解。

进入 collections 的良好起点: Excel Collection Ultimate Guide 绝对重要的主题,因为大多数 for each 循环都迭代了 collections.

当您使用 redim 时,它实际上会创建一个指定大小的全新数组,因此所有现有数据都将丢失。要将值从旧数组复制到新数组,您需要 'Preserve' 关键字,如下所示

ReDim Preserve pAddresses(1)

但这确实效率低下,因为向数组添加另一个元素需要重写整个数组。您可能最好使用集合。所以不要像这样声明 pAddress

Private pAddresses() as Address  ' delcare as an array

这样做

Private pAddresses as New Collection ' declare as a collection

现在您添加地址的方法如下所示:

Public Sub addAddress(val as Address)
    pAddresses.Add val
End Sub

集合的索引从 1 而不是 0 开始计数(就像数组一样),因此下一行打印集合中的第一个条目

Debug.Print pAddresses(1)