为什么 VBA Me 关键字不能访问自己模块中的私有过程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1895633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can't the VBA Me keyword access private procedures in its own module?
提问by Kuyenda
I just discovered that the Me keyword cannot access private procedures even when they are inside its own class model.
我刚刚发现 Me 关键字无法访问私有过程,即使它们在自己的类模型中。
Take the following code in Class1:
在 Class1 中取以下代码:
Private Sub Message()
Debug.Print "Some private procedure."
End Sub
Public Sub DoSomething()
Me.Message
End Sub
This code instantiates an instance of the class:
此代码实例化该类的一个实例:
Sub TestClass()
Dim objClass As New Class1
objClass.DoSomething
End Sub
Me.Message
throws compile error "Method or data member not found."
Me.Message
抛出编译错误“未找到方法或数据成员”。
If I change Private Sub Message()
to Public
the procedure works fine. I can also remove the Me keyword from the DoSomething procedure, but I was under the impression that the idea behind the Me keyword is to ensure that multiple instances of Class1 are properly encapsulated.
如果我改变Private Sub Message()
到Public
的程序工作正常。我也可以从 DoSomething 过程中删除 Me 关键字,但我的印象是 Me 关键字背后的想法是确保正确封装 Class1 的多个实例。
Why can't the VBA Me keyword access procedures in its own module when they are private? Is it safe to omit the Me keyword and do something like this in a class?
为什么 VBA Me 关键字在私有时不能访问其自身模块中的程序?省略 Me 关键字并在课堂上做这样的事情是否安全?
Private Sub Message()
Debug.Print "Some private procedure."
End Sub
Public Sub DoSomething()
Message
End Sub
Thanks!
谢谢!
Update: Thanks for the tips on proper syntax, my code is working. I am still looking for an explanation of whyMe can reference private procedures in an instance of it's own module. I couldn't find any good documentation.
更新:感谢有关正确语法的提示,我的代码正在运行。我仍在寻找有关为什么Me 可以在它自己的模块的实例中引用私有过程的解释。我找不到任何好的文档。
采纳答案by Oorang
Any guess as to why it was designed that way would be pure supposition without talking to the designers. But my own guess is this, the Mekeyword returns a reference to the object the code is currently executing in. I would guess rather than create a special case for Me, they found it easier to continue to obey rules of scope for an object. Which is to say object.method can only work on public or friend methods. So Me, is exactly what it says, an instance of an the currently executing object. And since VBA/VB6 doesn't have shared methods, it doesn't really matter if you prefix with Me or not.
任何关于为什么以这种方式设计的猜测都将是纯粹的假设,而无需与设计师交谈。但我自己的猜测是,Me关键字返回对当前正在执行代码的对象的引用。我猜测与其为 Me 创建一个特例,他们发现继续遵守对象的范围规则更容易。也就是说 object.method 只能在公共或友元方法上工作。所以我,正是它所说的,一个当前正在执行的对象的实例。而且由于 VBA/VB6 没有共享方法,所以是否以 Me 为前缀并不重要。
But if it makes you feel any better, I find it incredibly obnoxious too.
但如果它让你感觉更好,我也觉得它非常令人讨厌。
回答by Mitch Wheat
You do not need the Me
keyword to call inside own class.
您不需要Me
关键字在自己的类中调用。
回答by Lins
Me is this class object instance. So no one can directly call private subs or functions or access private variables except this class public functions or subs.
我是这个类的对象实例。因此,除了此类公共函数或子程序之外,没有人可以直接调用私有子程序或函数或访问私有变量。
回答by Bas de Jong
Public Function Fight() As String
'performs a round of attacks i.e. each character from both sides performs an attack
'returns a scripted version of the outcomes of the round
'check if buccaneers are all dead
If mBuccaneers.aliveCount > 0 Then
'check if any hostiles are alive
If mHostiles.aliveCount > 0 Then
'check we have some buccaneers
If mBuccaneers.count = 0 Then
Fight = "There are no buccaneers. Load or create some buccaneers"
Else
If mHostiles.count = 0 Then
'can't fight
Fight = "There are no hostiles to fight. Generate some hostiles"
Else
mScript = ""
Call GroupAttack(mBuccaneers, mHostiles)
Call GroupAttack(mHostiles, mBuccaneers)
Fight = mScript
End If
End If
Else 'hostiles are all dead
Fight = "Hostiles are all dead. Generate a new set of hostiles"
End If
Else
Fight = "Buccaneers are all dead :(. Suggest building or loading a new buccaneer group"
End If
End Function
Uses the private class method GroupAttack by using the Call statement
通过使用 Call 语句使用私有类方法 GroupAttack
Private Sub GroupAttack(attackersGroup As clsGroup, defendersGroup As clsGroup)
'implements the attack of one group on another
Dim victimNo As Integer
Dim randomNumber As Integer
Dim attacker As clsCharacter
Dim damage As Integer
Dim defender As clsCharacter
Randomize
For Each attacker In attackersGroup.members
'check if attacker is still alive
If attacker.health > 0 Then
'check if any defenders are still alive because there's no point attacking dead defenders
If defendersGroup.aliveCount > 0 Then
'do some damage on a defender
If defendersGroup.count > 0 Then
'choose a random hostile
victimNo = Int(((Rnd() * defendersGroup.aliveCount) + 1))
'find an alive victim
memberid = 0
j = 0
Do While j < victimNo
memberid = memberid + 1
If defendersGroup.members(memberid).health > 0 Then
j = j + 1
End If
Loop
'reset our victimno to the live victim
victimNo = memberid
damage = defendersGroup.character(victimNo).attack(attacker.strength)
If damage <> 0 Then 'attacker hit
mScript = mScript & attacker.name & " hits " & _
defendersGroup.character(victimNo).name & " for " & damage & " damage"
If defendersGroup.character(victimNo).health = 0 Then
mScript = mScript & " and kills " & defendersGroup.character(victimNo).name
End If
mScript = mScript & vbCrLf
Else 'attacker missed
mScript = mScript & attacker.name & " missed " & defendersGroup.character(victimNo).name & vbCrLf
End If
End If
End If
End If
Next attacker
End Sub
Thats all you need to do ,works like a charm
这就是你需要做的一切,就像一个魅力
回答by supercat
In COM, there's a difference between the types of object instances and the types of object variables. In particular, the types of object variables behave as interface types. Every type implements at least one interface (itself), but types may implement other interfaces as well. Such ability is used to fake inheritance.
在 COM 中,对象实例的类型和对象变量的类型是不同的。特别是,对象变量的类型表现为接口类型。每种类型至少实现一个接口(本身),但类型也可以实现其他接口。这种能力被用来伪造继承。
In some frameworks, if class Foo
has a private member Bar
, then any non-null variable of type Foo
will hold a reference to some class object which contains that member. The member may not be accessible to any outside code, but it will exist, and can thus be accessed from anywhere within the code for Foo
.
在某些框架中,如果 classFoo
有一个 private member Bar
,那么任何类型的非空变量都Foo
将持有对包含该成员的某个类对象的引用。该成员可能无法被任何外部代码访问,但它会存在,因此可以从Foo
.
Because COM class-variable types behave like interfaces rather than inheritable class types, however, there's no guarantee that a variable of type Foo
will refer to an object which has any of Foo
's non-public members. While a compiler could know that Me
will always refer to the present object, which will be of actual type Foo
, the fact that the only object upon which a private member of Foo
could be accessed is Me
means that there's no real reason for the compiler to support dot-based dereferencing of private members.
但是,由于 COM 类变量类型的行为类似于接口而不是可继承的类类型,因此不能保证类型的变量Foo
将引用具有 任何Foo
非公共成员的对象。虽然编译器可以知道Me
将始终引用当前对象,该对象将是实际类型Foo
,但事实上Foo
可以访问的私有成员的唯一对象Me
意味着编译器没有真正的理由支持点-基于私有成员的取消引用。