再次调查后,我有了答案,但并不完全令人满意。与 VBA 中的大多数 OOP 一样,它涉及使用适当的接口,但是每个类(和每个接口)都必须放在单独的类模块中,这使得它成为一种非常笨拙的做事方式。所以这里是:
假设我有一个名为 MyClass 的类(我在上面称它为“C”,但我现在称它为“MyClass”以使这一点更清楚。)
要做的事情是定义一个我会在我的代码中实际使用的接口,它只公开我想要真正公开的关于 MyClass 的东西。假设这段代码在一个名为 IMyClass 的类模块中:
Public Function calcSomething()
End Function
Public Function equal(cinst As IMyClass) As Boolean
End Function
然后我有一个名为 MyClass 的类,在类模块中使用以下代码定义:
Implements IMyClass
Private hidden1_ As Double
Private hidden2_ As Double
Public Sub init(h1 As Double, h2 As Double)
hidden1_ = h1
hidden2_ = h2
End Sub
Public Function equalDef(hidden1 As Double, hidden2 As Double) As Boolean
equalDef = (hidden1_ = hidden1 And hidden2_ = hidden2)
End Function
Private Function IMyClass_calcSomething() As Variant
IMyClass_calcSomething = hidden1_ * hidden2_
End Function
Private Function IMyClass_equal(cinst As IMyClass) As Boolean
If TypeOf cinst Is MyClass Then
Dim asMyClass As MyClass
Set asMyClass = cinst
IMyClass_equal = asMyClass.equalDef(hidden1_, hidden2_)
End If
End Function
下面是一些可以放在常规模块中的代码:
Public Function mkMyClass(h1 As Double, h2 As Double) As IMyClass
Dim ret As MyClass
Set ret = New MyClass
Call ret.init(h1, h2)
Set mkMyClass = ret
End Function
Public Sub useMyClass()
Dim mc1 As IMyClass
Set mc1 = mkMyClass(42, 99)
Dim mc2 As IMyClass
Set mc2 = mkMyClass(42, 99)
Dim mc3 As IMyClass
Set mc3 = mkMyClass(99, 42)
Debug.Print mc1.calcSomething
Debug.Print mc1.equal(mc2)
Debug.Print mc3.calcSomething
Debug.Print mc3.equal(mc2)
End Sub
在 'useMyClass' 例程中,您可以验证各种 mc1、mc2 和 mc3 变量看不到 MyClass 的 'init' 或 'equalDef' 方法。他们只能看到作为接口一部分的“calcSomething”和“equal”方法。
所以,我猜,这个问题正式但不令人满意地回答了。至少它让我有机会重复“VBA 中的 OOP 是 PITA (TM)”......
以下是一些相关的stackoverflow答案:
VBA继承,super的类比
有没有办法重载VBA中类的构造函数/初始化过程?