2009-12-13 10 views
11

Ho appena scoperto che la parola chiave Me non può accedere alle procedure private anche quando si trovano all'interno del proprio modello di classe.Perché la parola chiave VBA Me non può accedere alle procedure private nel proprio modulo?

Prendere il seguente codice nel Class1:

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

Public Sub DoSomething() 
    Me.Message 
End Sub 

Questo codice crea un'istanza di un un'istanza della classe: "membro di metodo o dati non trovato"

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

Me.Message tiri Errore di compilazione

Se cambio Private Sub Message() in Public, la procedura funziona correttamente. Posso anche rimuovere la parola chiave Me dalla procedura DoSomething, ma ho avuto l'impressione che l'idea alla base della parola chiave Me sia quella di garantire che più istanze di Class1 siano incapsulate correttamente.

Perché non è possibile accedere alle procedure di accesso alle parole chiave VBA Me nel proprio modulo quando sono private? È sicuro omettere la parola chiave Me e fare qualcosa di simile in una classe?

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

Public Sub DoSomething() 
    Message 
End Sub 

Grazie!

Aggiornamento: Grazie per i suggerimenti sulla sintassi corretta, il mio codice funziona. Sto ancora cercando una spiegazione di perché Me può fare riferimento a procedure private in un'istanza del proprio modulo. Non ho trovato alcuna buona documentazione.

risposta

5

Qualsiasi ipotesi sul motivo per cui è stata progettata in questo modo sarebbe pura supposizione senza parlare con i progettisti. Ma la mia ipotesi è questa, la parola chiave Me restituisce un riferimento all'oggetto in cui il codice è attualmente in esecuzione. Direi piuttosto che creare un caso speciale per Me, hanno trovato più semplice continuare a obbedire alle regole di ambito per un oggetto. Il che vuol dire che object.method può funzionare solo su metodi pubblici o amici. So Me, è esattamente ciò che dice, un'istanza di un oggetto attualmente in esecuzione. E poiché VBA/VB6 non ha metodi condivisi, non importa se si prefissa o meno con Me.

Ma se ti fa sentire meglio, lo trovo anche incredibilmente antipatico.

+2

ha un senso. Sembra come 'Me' è una scorciatoia per creare ipoteticamente una variabile oggetto (' Dim Me As Object') e impostare quella variabile sull'oggetto in cui si trova il codice ('Set Me = ThisModule'. Quella variabile oggetto avrebbe comunque accesso alle proprietà e alle procedure del modulo dall'esterno Grazie! – Kuyenda

3

Non è necessaria la parola chiave Me da chiamare all'interno della propria classe.

+0

A meno che non ci sia qualche ombra :( – mlvljr

0

Me è questa istanza di oggetto di classe. Quindi nessuno può chiamare direttamente sottotitoli o funzioni private o accedere a variabili private ad eccezione di queste funzioni pubbliche o sottotitoli di classe.

0

In COM, c'è una differenza tra i tipi di istanze dell'oggetto e i tipi di variabili oggetto. In particolare, i tipi di variabili oggetto si comportano come tipi di interfaccia. Ogni tipo implementa almeno un'interfaccia (stessa), ma i tipi possono implementare anche altre interfacce. Tale abilità viene utilizzata per falsificare l'ereditarietà.

In alcuni contesti, se la classe Foo presenta un organo privato Bar, allora qualsiasi variabile non nulla di tipo Foo terrà un riferimento a un oggetto classe che contiene tale membro. Il membro potrebbe non essere accessibile a nessun codice esterno, ma esiste e può quindi essere accessibile da qualsiasi posizione all'interno del codice per Foo.

Poiché i tipi di variabile di classe COM si comportano come interfacce anziché tipi di classi ereditabili, tuttavia, non è possibile garantire che una variabile di tipo Foo faccia riferimento a un oggetto che include uno dei membri non pubblici di . Mentre un compilatore potrebbe sapere che Me si riferirà sempre al presente oggetto, che sarà del tipo effettivo Foo, il fatto che l'unico oggetto su cui un membro privato di Foo sia accessibile è Me significa che non c'è un vero motivo per il compilatore supportare la dereferenziazione basata su punti di membri privati.

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 

utilizza il metodo classe privata GroupAttack utilizzando l'istruzione 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 

Questo è tutto quello che devi fare, funziona come un fascino

Problemi correlati