2009-12-13 7 views
11

Je viens de découvrir que le mot-clé Me ne peut pas accéder aux procédures privées même lorsqu'elles sont dans son propre modèle de classe.Pourquoi le mot clé VBA Me ne peut-il pas accéder aux procédures privées dans son propre module?

Prenez le code suivant dans Class1:

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

Public Sub DoSomething() 
    Me.Message 
End Sub 

Ce code instancie une instance de la classe:

Sub TestClass() 
    Dim objClass As New Class1 
    objClass.DoSomething 
End Sub 

Me.Message lancers francs compilent erreur "Méthode ou membre de données non trouvé." Si je change Private Sub Message() en Public, la procédure fonctionne correctement. Je peux également supprimer le mot-clé Me de la procédure DoSomething, mais j'avais l'impression que l'idée derrière le mot-clé Me est de s'assurer que plusieurs instances de Class1 sont correctement encapsulées. Pourquoi le mot clé VBA Me ne peut-il pas accéder aux procédures dans son propre module quand elles sont privées? Est-il prudent d'omettre le mot-clé Me et de faire quelque chose comme ça dans une classe?

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

Public Sub DoSomething() 
    Message 
End Sub 

Merci!

Mise à jour: Merci pour les conseils sur la bonne syntaxe, mon code fonctionne. Je suis toujours à la recherche d'une explication de pourquoi Me peut référencer des procédures privées dans une instance de son propre module. Je n'ai pas trouvé de bonne documentation.

Répondre

5

Tout deviner pourquoi il a été conçu de cette façon serait pure supposition sans en parler aux concepteurs. Mais ma propre supposition est la suivante: le mot-clé Me renvoie une référence à l'objet dans lequel le code s'exécute actuellement. Je suppose plutôt que de créer un cas spécial pour Moi, ils ont trouvé plus facile de continuer à obéir aux règles de portée d'un objet. C'est-à-dire que object.method ne peut fonctionner que sur des méthodes publiques ou friend. So Me, est exactement ce qu'il dit, une instance d'un objet en cours d'exécution. Et puisque VBA/VB6 n'a pas de méthodes partagées, cela n'a pas vraiment d'importance si vous préférez Moi ou non.

Mais si cela vous fait vous sentir mieux, je le trouve aussi incroyablement désagréable.

+2

sens. Semble comme 'Me' est un raccourci pour créer une variable d'objet hypothétiquement (' Dim Me As Object') et mettre cette variable à l'objet dans lequel le code est ('Set Me = ThisModule'.) Cette variable d'objet accèderait toujours aux propriétés et procédures du module de l'extérieur Merci! – Kuyenda

3

Vous n'avez pas besoin du mot-clé pour appeler dans sa propre classe.

+0

moins qu'il y ait shadowing :( – mlvljr

0

Me est cette instance d'objet de classe. Donc, personne ne peut directement appeler des sous-marins privés ou des fonctions ou accéder à des variables privées à l'exception de cette classe fonctions publiques ou sous-marins.

0

Dans COM, il existe une différence entre les types d'instances d'objet et les types de variables d'objet. En particulier, les types de variables d'objet se comportent comme des types d'interface. Chaque type implémente au moins une interface (elle-même), mais les types peuvent également implémenter d'autres interfaces. Une telle capacité est utilisée pour simuler l'héritage.

Dans certains cadres, si la classe Foo a un membre privé Bar, toute variable non nulle de type Foo tiendra une référence à un objet de classe qui contient ce membre. Le membre ne peut être accessible à aucun code extérieur, mais il existera, et peut donc être accessible à partir de n'importe où dans le code pour Foo.Comme les types de variable de classe COM se comportent comme des interfaces plutôt que comme des types de classe pouvant être hérités, il n'y a aucune garantie qu'une variable de type Foo fera référence à un objet qui possède l'un des membres non publics de Foo. Alors qu'un compilateur pourrait savoir que Me se référera toujours à l'objet actuel, qui sera de type réel Foo, le fait que le seul objet sur lequel un membre privé de Foo peut être consulté est signifie qu'il n'y a pas de véritable raison pour le compilateur soutenir le déréférencement par points des membres privés.

0
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 

utilise la méthode de la classe privée GroupAttack en utilisant l'instruction Call

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 

C'est tout ce que vous devez faire, fonctionne comme un charme