首页 > 解决方案 > 我必须为以下课程使用 getter 和 setter 吗?

问题描述

所以,我需要一个类,它的结构如下:

Obj
    .Name
        .value as string
        .tag as string
    .Id
        .value as string
        .tag as string

这些valuetag成员变量可以从外部访问。所以我尝试使用 Types 编写一个类。

'make a "RefPairType" Type for value/tag pair 
Public Type RefPairType
    value As String
    tag as String
End Type

'Make member vars of the class based on RefPairType 
Private Name As RefPairType
Private Id As RefPairType

显然,由于这些成员是私有的,我无法在模块级别与他们进行交互。模块级别的代码:

Private Sub Document_New()
    'create an exemplar of aforementioned Class called "Class1"
    Dim client As New Class1

    'try to assign value to the member:
    client.Name.value = "foo"
    'COMPILE ERROR: method or data member not found
End Sub

如果我将这些类型或成员变量公开,我会得到错误:

'Cannot define a public user-defined type within an object module

或者

'constants, ... user-defined types not allowed as public members of object modules

这是否意味着我必须为类的每个成员变量创建 getter/setter?如果我的班级规模扩大 10 倍怎么办?我如何为像 object.name.tag 这样的嵌套成员创建 getter 和 setter?

标签: vba

解决方案


AType不是一个类,也不是一个对象。它只不过是一块具有特定布局的内存。如果你有一些你可以拥有的实例,你可以New启动,那么你不需要一个Type,而是一个类模块。用户定义的类型有很多限制,使得它们很难使用,至少从 OOP 的角度来看是这样。

在这种情况下,您想要 aValueTagPair或其他东西,可能看起来像这样 - 请注意如何Private Type仍然可以使用 a 将实例状态保存在单个私有字段 ( this) 下:

Option Explicit
Private Type TPair
    Value As String 
    Tag As String
End Type
Private this As TPair

Public Property Get Value() As String
    Value = this.Value
End Property

Public Property Let Value(ByVal rhs As String)
    this.Value = rhs
End Property

Public Property Get Tag() As String
    Tag = this.Tag
End Property

Public Property Let Tag(ByVal rhs As String)
    this.Tag = rhs
End Property

现在您可以声明任何变量As ValueTagPair,并按原样使用它——包括作为Property另一个类的成员的返回类型。

Option Explicit
Private Type TSomething
    Name As ValueTagPair
    Id As ValueTagPair
End Type
Private this As TSomething

Public Property Get Name() As ValueTagPair
    Set Name = this.Name
End Property

Public Property Get Id() As ValueTagPair
    Set Id = this.Id
End Property

Private Sub Class_Initialize()
    Set this.Name = New ValueTagPair
    Set this.Id = New ValueTagPair
End Sub

现在假设这是一个Something类,我们现在可以这样做:

Dim thing As Something
Set thing = New Something
thing.Name.Tag = "name-tag"
thing.Name.Value = "name-value"
thing.Id.Tag = "id-tag"
thing.Id.Value = "id-value"

如果您需要能够这样做Set thing.Name = New ValueTagPair,那么您必须公开该属性的Public Property Set成员。Name

这是否意味着我必须为类的每个成员变量创建 getter/setter?

是的。类的公共成员定义了该类的接口,而接口决定了如何使用对象。如果Class1.Name没有暴露在 的接口上Class1,则不存在;早期绑定的使用不会编译,后期绑定的成员调用(即针对Objector进行的调用Variant)将在运行时崩溃并出现错误 438。

如果我的班级规模扩大 10 倍怎么办?

那么它可能有太多的责任。具有明确和明确目的的对象通常不会做 20 件事。


推荐阅读