在 VBA 中实现接口时,实现的功能需要是私有的还是公共的?

Ant*_*yer 3 oop excel vba interface implements

我正在阅读这里创建类工厂:https : //rubberduckvba.wordpress.com/2018/04/24/factories-parameterized-object-initialization/我很困惑为什么他们将实现的函数设为私有,不会我们希望它们是公开的,以便我们可以访问它们?

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "Something"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Type TSomething
    Bar As Long
    Ducky As String
End Type

Private this As TSomething
Implements ISomething

Public Function Create(ByVal initialBar As Long, ByVal initialDucky As String) As ISomething
    With New Something
        .Bar = initialBar
        .Ducky = initialDucky
        Set Create = .Self
    End With
End Function

Public Property Get Self() As ISomething
    Set Self = Me
End Property

Public Property Get Bar() As Long
    Bar = this.Bar
End Property

Friend Property Let Bar(ByVal value As Long)
    this.Bar = value
End Property

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

Friend Property Let Ducky(ByVal value As String)
    this.Ducky = value
End Property

Private Property Get ISomething_Bar() As Long
    ISomething_Bar = Bar
End Property

Private Property Get ISomething_Ducky() As String
    ISomething_Ducky = Ducky
End Property
Run Code Online (Sandbox Code Playgroud)

另外,为什么需要为接口中的公共变量提供 get 和 let 属性?

Mat*_*don 7

他们应该是Private

原因是因为接口在 VBA 中是如何工作的:Public类模块的成员定义了它的默认接口。这意味着公共成员Class1定义了成员Class2必须实现的内容Implements Class1

因此,如果您Class1_DoSomething公开,那么您将在 的默认接口上公开该成员Class2,这……一点也不漂亮。

您访问对象的接口取决于您如何声明它。

Dim thing As Class1
Set thing = New Class1
Run Code Online (Sandbox Code Playgroud)

如果thingis或 implements Class1,则此声明之后的代码可以调用默认接口公开的所有成员Class1(即其公共成员)。

如果Class1实现ISomething并且我们像这样声明它:

Dim thing As ISomething
Set thing = New Class1
Run Code Online (Sandbox Code Playgroud)

现在我们要使用的成员是由ISomething类/接口的公共成员定义的成员。

当你实现一个接口或处理事件时,你永远不应该手动输入签名;相反,从代码窗格的左上角下拉列表中选择接口(或事件提供程序),然后从右上角的下拉列表中选择一个成员:VBE 会自动创建具有正确签名的正确过程,并且它始终是一个Private成员-拇指法则,任何有下划线在VBA中的名称有没有业务Public


至于为什么必须为接口类上定义为公共字段(/变量)的内容提供GetLet访问器......字段是实现细节,它们永远不应该Public放在首位。对象公开属性,而不是字段 - 为实现类的私有内部状态保留字段。

原因是技术性的:VBA 代码被编译成一个 COM 类型库,该库看到您的公共变量并说“这将必须是一个 PUT 和一个 GET 方法”,因此实现该接口的 VBA 代码需要实现每个公共字段的属性,因为公共字段编译为属性。

这对于在类模块上公开公共字段的做法确实具有有趣的含义(无论如何都将封装与编译分解为属性!),但这是另一个讨论。