为什么可以';VBA Me关键字是否在其自己的模块中访问私有过程?

为什么可以';VBA Me关键字是否在其自己的模块中访问私有过程?,vba,scope,encapsulation,Vba,Scope,Encapsulation,我刚刚发现Me关键字无法访问私有过程,即使它们位于自己的类模型中 以Class1中的以下代码为例: Private Sub Message() Debug.Print "Some private procedure." End Sub Public Sub DoSomething() Me.Message End Sub 此代码实例化类的一个实例: Sub TestClass() Dim objClass As New Class1 objClass.DoSo

我刚刚发现Me关键字无法访问私有过程,即使它们位于自己的类模型中

以Class1中的以下代码为例:

Private Sub Message()
    Debug.Print "Some private procedure."
End Sub

Public Sub DoSomething()
    Me.Message
End Sub
此代码实例化类的一个实例:

Sub TestClass()
    Dim objClass As New Class1
    objClass.DoSomething
End Sub
Me.Message
抛出编译错误“未找到方法或数据成员”

如果我将
Private Sub Message()
更改为
Public
,该过程工作正常。我还可以从DoSomething过程中删除Me关键字,但我的印象是,Me关键字背后的思想是确保正确封装Class1的多个实例

当VBA Me关键字访问过程是私有的时,为什么它们不能在自己的模块中访问?在类中省略Me关键字并执行类似操作安全吗

Private Sub Message()
    Debug.Print "Some private procedure."
End Sub

Public Sub DoSomething()
    Message
End Sub
谢谢


更新:感谢您提供正确语法的提示,我的代码正在运行。我仍然在寻找一个解释,说明为什么我可以在自己模块的实例中引用私有过程。我找不到任何好的文档。

您不需要在自己的类中调用
Me
关键字。

任何关于它为什么以这种方式设计的猜测都是纯粹的假设,不需要与设计人员交谈。但我自己的猜测是,关键字返回对代码当前正在执行的对象的引用。我想,与其为
Me
创建一个特例,不如让他们更容易继续遵守对象的范围规则。也就是说,
object.method
只能在public或friend方法上工作。因此,
Me
,就是它所说的,当前正在执行的对象的一个实例。由于VBA/VB6没有共享的方法,所以是否使用
Me
作为前缀并不重要


但是如果它能让你感觉好一点,我也会觉得它非常讨厌。

Me就是这个类对象实例。因此,除了此类公共函数或子函数外,没有人可以直接调用私有子函数或函数或访问私有变量。

在COM中,对象实例的类型和对象变量的类型是不同的。特别是,对象变量的类型表现为接口类型。每个类型至少实现一个接口(自身),但类型也可以实现其他接口。这种能力被用来伪造继承

在某些框架中,如果类
Foo
有一个私有成员
Bar
,那么
Foo
类型的任何非空变量都将包含对包含该成员的某个类对象的引用。任何外部代码都可能无法访问该成员,但它将存在,因此可以从
Foo
的代码中的任何位置访问该成员

由于COM类变量类型的行为类似于接口,而不是可继承的类类型,因此不能保证
Foo
类型的变量将引用具有任何
Foo
非公共成员的对象。虽然编译器可能知道
Me
将始终引用当前对象,该对象将是实际类型的
Foo
,可以访问
Foo
私有成员的唯一对象是
Me
,这意味着编译器没有真正的理由支持基于点的私有成员解引用

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
通过使用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
Private子组攻击(attackersGroup作为clsGroup,defendersGroup作为clsGroup)
'实施一个组对另一个组的攻击
Dim victimNo为整数
将随机数设置为整数
暗淡的攻击者,如Clschracter
模糊损伤为整数
弱小的防守球员,就像一名球员
随机化
针对attackersGroup.members中的每个攻击者
'检查攻击者是否仍然活着
如果攻击者.health>0,则
检查是否有防守队员还活着,因为攻击死去的防守队员没有意义
如果DefenderGroup.aliveCount>0,则
“对防守者造成一些伤害
如果DefenderGroup.count>0,则
"随便选一个,
受害者编号=Int(((Rnd()*defendergroup.aliveCount)+1))
“找到一个活着的受害者
memberid=0
j=0
当j0,则
j=j+1
如果结束
环
'将我们的受害者编号重置为活的受害者
受害者编号=成员ID
伤害=防御者组。角色(受害者号)。攻击(攻击者。力量)
如果伤害为0,则“攻击者”命中
mScript=mScript&attacker.name&“hits”&_
辩护人组。人物(受害者编号)。姓名和“代表”&伤害和“伤害”
如果DefenderGroup.character(受害者编号).health=0,则
mScript=mScript&“and kills”&defendergroup.character(受害者编号)。name
如果结束
mScript=mScript&vbCrLf
其他人的袭击者没有击中
mScript=mScript&attacker.name&“missed”&defendersGroup.character(受害者编号)。name&vbCrLf
如果结束
如果结束
如果结束
如果结束
下一个攻击者
端接头

这就是你所需要做的,就像一个符咒一样有效。似乎
Me
是假设创建对象变量(
Dim Me As object
)并将该变量设置为代码所在的对象(
Set Me=ThisModule
)的缩写。该对象变量仍将从外部访问模块属性和过程。谢谢!除非有阴影:(该问题目前适用于程序,但可以概括为包括所有类型的私人成员:
Me
不能用于访问私人成员,