为什么要在 VBA 类模块中声明新类型?

lam*_*tin 3 mvp vba types module class

我想遵循 Mathieu Guindon在这个优秀答案中描述的 MVP Userform 架构。但是,我不明白为什么在 FilterModel 类模块以及 FilterForm Userform 模块中,在类中创建了新类型,然后将其元素重新声明为类的属性。为什么这是必要的?为什么不将 SelectedFilter 声明为字符串类型的属性?我错过了什么吗?

Mat*_*don 5

大多数属性需要一个支持字段。通常它看起来像这样:

Option Explicit
Private mFoo As String

Public Property Get Foo() As String
    Foo = mFoo
End Property

Public Property Let Foo(ByVal value As String)
    mFoo = value
End Property
Run Code Online (Sandbox Code Playgroud)

当您在locals工具窗口中查看该类的实例时,您将同时看到mFoo私有支持字段和公共Foo属性 - 当该类有多个成员时,它很快就会变得嘈杂。

另外,我真的不喜欢这种m前缀方案,但是由于 VBA 不区分大小写,因此您不能拥有属性的foo支持字段Foo

通过声明 aPrivate Type来保存封装的实例状态...

Private Type InternalState
    Foo As String
End Type
Private this As InternalState

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

Public Property Let Foo(ByVal value As String)
    this.Foo = value
End Property
Run Code Online (Sandbox Code Playgroud)

...现在属性及其支持字段可以使用相同的标识符,不需要任何前缀,我们得到了所有成员的自动完成列表this,并且 locals 工具窗口现在将实例状态值分组在 下this,唯一的私有字段在类中,这使得调试工具更加简洁。

这不是必需品,但我找不到不这样做的好理由。这实际上是一种风格/偏好,而不是最佳实践,但它有明显的好处。


为什么不将 SelectedFilter 声明为字符串类型的属性?

如果这意味着“为什么不声明一个字符串类型的公共字段”,那么这是一个不同的问题,有不同的答案。

每个类都定义了一个默认接口,其成员是类的Public成员。但是,接口不公开领域,所以如果你有一个类中的公共领域,它的默认界面将Property GetProperty Let/Set它的存取:通过定义明确的Property成员,而不仅仅是一个公共领域,你可以将这个类定义其默认一致界面。..并且您正在封装内部状态 -封装作为 OOP 的 4 大支柱之一:没有业务公开的东西不应该公开。使用属性,您可以控制后备私有字段的分配方式:类之外的任何人都无法访问它。例如,如果外部代码尝试分配Foo给空字符串或与某些正则表达式模式不匹配的字符串,您可能需要运行一些验证逻辑并引发错误。

使用属性与公共字段的优势超出了这个问题的范围(并且已经在其他地方回答过),但是该主题与语言无关,因此不必将您的研究局限于 VBA:使用的原因(或不)属性与公共字段在 VBA 中与在 Java 或 C# 中相同。