有没有办法为具有私有成员的 VBA 类编写相等测试而不暴露这些私有成员的存在?
我进行了大量的 Excel VBA 编程,但其中并不是很多都是面向对象的。时不时就会出现一些让我烦恼的事情,我想知道我是否遗漏了一些东西。
在 VBA 中,假设我有一个类 C 定义了一些私有成员,如下所示:
'...
Private hidden1_ As Double
Private hidden2_ As Double
'...
如果 VBA 像 C++ 或(大多数?)其他支持 OOP 的语言一样工作,我可以编写一个成员函数来在类 C 的实例之间进行相等测试,例如this:
'Error: won't compile!
Public Function equal(cinst As C) As Boolean
equal = (hidden1_ = cinst.hidden1_ And hidden2_ = cinst.hidden2_)
End Function
当然,这不会在 VBA 中编译,因为类成员函数只能访问调用它们的同一实例的私有类成员。我想到的最好的做法是定义两个成员函数,如下所示:
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
它很麻烦,并且暴露了私有类成员存在的知识,但至少它避免了实际暴露 私有类成员的值。
这是我能做的最好的事情吗?
编辑:
像往常一样,在回答之后,我意识到了一种更好的方式来表达问题。它的标题是“是否有更简洁的方法来为具有私有成员的 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.
In VBA, say I have a class C defined with some private members like so:
'...
Private hidden1_ As Double
Private hidden2_ As Double
'...
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
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
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?
EDIT:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我会像这样编写类
如果您无论如何都被迫公开成员的知识,您不妨将其设为只读属性(Get,但不让)。然后您可以在类中创建 IsEquivalent 布尔属性。
I would write the class like this
If you're forced to expose knowledge of the member anyway, you may as well make it a read-only property (Get, but no Let). Then you can make the IsEquivalent boolean property inside the class.
再次研究这个问题后,我有了答案,但并不完全令人满意。与 VBA 中的大多数 OOP 一样,它涉及使用适当的接口,但每个类(以及每个接口)都必须位于单独的类模块中,这一事实使其成为一种相当笨拙的执行方式。所以这里是:
假设我有一个名为 MyClass 的类(上面我将其称为“C”,但现在我将其称为“MyClass”以使这一点更清楚。)
要做的事情是定义一个我实际使用的接口在我的代码中,只公开了我想要真正公开的有关 MyClass 的内容。假设这段代码位于一个名为 IMyClass 的类模块中:
然后我有一个名为 MyClass 的类,在类模块中使用此代码进行定义:
下面是一些将放入常规模块中的代码:
在 'useMyClass' 例程中,您可以验证各个 mc1、mc2 和 mc3 变量看不到 MyClass 的 'init' 或 'equalDef' 方法。他们只能看到属于接口一部分的“calcSomething”和“equal”方法。
所以,我想,这个问题是正式提出的,但答案并不令人满意。至少它让我有机会重复“VBA 中的 OOP 是 PITA (TM)”...
以下是一些相关的 stackoverflow 答案:
VBA继承,super的模拟
有没有办法重载 VBA 中类的构造函数/初始化过程?
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:
Say I have a class called MyClass (which I was calling 'C' above but I'm now calling 'MyClass' to make this clearer.)
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:
Then I have my class called MyClass, defined with this code in a class module:
And here is some code that would go in a regular module:
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.
So, question officially but unsatisfyingly answered, I guess. At least it gives me a chance to repeat "OOP in VBA is a PITA (TM)"...
Here are some related stackoverflow answers:
VBA inheritance, analog of super
Is there a way to overload the constructor / initialize procedure for a class in VBA?
我知道这是一篇旧帖子,但我仍然想回答。以下代码不向用户公开任何私有变量,并且仍然允许在对象之间进行比较:
具有以下输出:
I know this is an old post, but I would still like to answer. The following code exposes no private variables to the user and still allows comparison between objects:
With the following output: