有没有办法在不暴露那些私有成员存在知识的情况下为具有私有成员的VBA类编写平等测试的方法? [英] Is there a way to write an equality test for a VBA class with private members without exposing knowledge of the existence of those private members?

查看:93
本文介绍了有没有办法在不暴露那些私有成员存在知识的情况下为具有私有成员的VBA类编写平等测试的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了很多Excel VBA编程,但是其中很多不是面向对象的.这是不时出现的东西,让我感到烦恼,我想知道是否有我想念的东西.

I do a fair amount of Excel VBA programming, but not a lot of it is object-oriented. Here is something that comes up every now and then that bugs me, and I'm wondering if there's something I'm missing.

在VBA中,说我有一个由一些私有成员定义的C类,如下所示:

In VBA, say I have a class C defined with some private members like so:

'...

Private hidden1_ As Double
Private hidden2_ As Double

'...

如果VBA像C ++或(大多数?)其他支持OOP的语言一样工作,我可以编写一个成员函数来在类C的实例之间进行相等性测试:

If VBA worked like C++ or (most?) other languages that support OOP, I could write a member function to do an equality test between instances of class C like this:

'Error: won't compile!
Public Function equal(cinst As C) As Boolean
    equal = (hidden1_ = cinst.hidden1_ And hidden2_ = cinst.hidden2_)
End Function

当然,它不会在VBA中编译,因为类成员函数只能访问对其调用相同实例的私有类成员.我曾经想出的最好的办法是定义两个这样的成员函数:

Of course, that won't compile in VBA because class member functions can only access private class members of the same instance they are invoked on. The best I've ever come up with to do this sort of thing is to instead define two member functions like this:

Public Function equalDef(hidden1 As Double, hidden2 As Double) As Boolean
    equalDef = (hidden1_ = hidden1 And hidden2_ = hidden2)
End Function

Public Function equal(cinst As C) As Boolean
    equal = cinst.equalDef(hidden1_, hidden2_)
End Function

这很麻烦,并且公开了私有类成员的存在的知识,但至少可以避免实际上暴露私有类成员的 values .

It's cumbersome, and it exposes knowledge of the existence of private class members, but at least it avoids actually exposing the values of private class members.

这是我能做的最好的吗?

Is this the best I can do?

像往常一样,在回答之后,我意识到了表达问题的一种更好的方法.标题为是否有更干净的方法为带有私有成员的VBA类编写平等测试?"迪克回答时.

As usual, after an answer, I've realized a better way to phrase the question. It was titled "Is there a cleaner way to write an equality test for a VBA class with private members?" when Dick answered it.

推荐答案

再次研究这个问题之后,我有了一个答案,但这并不完全令人满意.与VBA中的大多数OOP一样,它涉及使用适当的接口,但是每个类(和每个接口)都必须进入单独的类模块这一事实使它成为一种笨拙的处理方式.所以去了:

After looking into this again, I have an answer, but it's not exactly satisfying. As with most OOP in VBA, it involves using an appropriate interface, but the fact that every class (and every interface) has to go in a separate class module makes it a pretty clunky way to do things. So here goes:

说我有一个名为MyClass的类(上面我叫'C',但现在我叫'MyClass'来使它更清楚.)

Say I have a class called MyClass (which I was calling 'C' above but I'm now calling 'MyClass' to make this clearer.)

要做的是定义一个我将在我的代码中实际使用的接口,该接口只暴露了我真正想要公开的有关MyClass的内容.说这段代码在一个名为IMyClass的类模块中:

The thing to do would be to define an interface that I would actually use in my code that exposed just the things about MyClass that I wanted truly public. Say this code is in a class module called IMyClass:

Public Function calcSomething()

End Function

Public Function equal(cinst As IMyClass) As Boolean

End Function

然后我有一个名为MyClass的类,该类是在类模块中用以下代码定义的:

Then I have my class called MyClass, defined with this code in a class module:

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

这是将在常规模块中使用的一些代码:

And here is some code that would go in a regular module:

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"方法.

In the 'useMyClass' routine, you can verify that the various mc1, mc2, and mc3 variables can't see the 'init' or 'equalDef' methods of MyClass. They can only see the 'calcSomething' and 'equal' methods that are part of the interface.

所以,我想是正式的问题,但回答不令人满意.至少它使我有机会重复"VBA中的OOP是PITA(TM)" ...

So, question officially but unsatisfyingly answered, I guess. At least it gives me a chance to repeat "OOP in VBA is a PITA (TM)"...

以下是一些相关的stackoverflow答案:

Here are some related stackoverflow answers:

VBA继承,类似于super

查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆