These two subs do the same thing when inside a class.
Sub DemoMe( )
Me.AboutMe ' Calls AboutMe procedure.
End Sub
Sub DemoMe( )
AboutMe ' Does the same thing.
End Sub
What is the point? Does the Me keyword do anything? What is the preferred way of an object accessing its own members?
The Me keyword behaves like an implicitly declared variable. It's automatically available to every procedure in a class module. When a class can have more than one instance, Me provides a way to refer to the specific instance of the class where the code is executing.
Use a class module to create a definition for a custom object. The name with which you save the class module becomes the name of your custom object. Public Sub and Function procedures that you define within a class module become custom methods of the object.
A class module is a group of code that allows you to create objects and utililise them in your application.
tldr; No, although there are situations where it can be useful.
From the VBA language specification (5.3.1.5):
Each procedure that is a method has an implicit ByVal parameter called the current object that corresponds to the target object of an invocation of the method. The current object acts as an anonymous local variable with procedure extent and whose declared type is the class name of the class module containing the method declaration. For the duration of an activation of the method the data value of the current object variable is target object of the procedure invocation that created that activation. The current object is accessed using the Me keyword within the <procedure-body> of the method but cannot be assigned to or otherwise modified.
That's all it is, just a "free" local variable that refers to the specific instance that the method is being called on. This also happens to be the default context for the procedures during their invocation, so it can be omitted if the code is intended to operate on the current instance. Although as @HansPassant points out in the comment above, it also allows the editor to bind to the interface and provide IntelliSense.
That said, there are a couple instances where you would either want to or have to use it (this is by no means an exhaustive list):
Naming collisions:
If your class has a member that "hides" a built-in VBA function, it can be used to make the scope explicit:
Public Property Get Left() As Long
'...
End Property
Public Property Get Right() As Long
'...
End Property
Public Property Get Width() As Long
Width = Me.Right - Me.Left
End Property
Equity Checks:
Public Function Equals(other As Object) As Boolean
If other Is Me Then
Equals = True
Exit Function
End If
'...
End Function
Fluent Functions:
This can be a useful pattern for compositing objects - you perform an action, then return the instance of the class so they can be "chained". Excel's Range
interface does this in a lot of cases:
Public Function Add(Value As Long) As Class1
'Do whatever.
Set Add = Me
End Function
Public Sub Foo()
Dim bar As New Class1
bar.Add(1).Add(1).Add 1
End Sub
Not any more than there are reasons to use this
in Java, C#, or any other language: it's a reserved identifier that represents the current instance of the class - what you do with that is up to your imagination.
What is the preferred way of an object accessing its own members?
Indeed, an object doesn't need the Me
keyword to access it own public interface. Same as this
in other languages, I'd even call it redundant. However it can sometimes be a good idea to explicitly qualify member calls with Me
, especially when the class has a VB_PredeclaredId
attribute (e.g. any UserForm
): referring to UserForm1
in the code-behind of UserForm1
yields a reference to the default instance of the class, whereas qualifying member calls with Me
yields a reference to the current instance of that class.
Accessing Inherited Members
VBA user code can't do class inheritance, but a lot of VBA classes do have a base class. The members of UserForm
when you're in the code-behind of UserForm1
, and those of Worksheet
when you're in the code-behind of Sheet1
, aren't necessarily easy to find. But since the inherited members show up in IntelliSense/auto-complete, you can type Me.
and browse a list of members inherited from the base class, members that you would otherwise need to know about in order to invoke.
A class creating an instance of itself inside itself? That I've never seen.
You're missing out! I do this all the time, to enable referring to the object instance held by a With
block, inside a Factory Method - like this GridCoord class.
Public Function Create(ByVal xPosition As Long, ByVal yPosition As Long) As IGridCoord
With New GridCoord
.X = xPosition
.Y = yPosition
Set Create = .Self
End With
End Function
Public Property Get Self() As IGridCoord
Set Self = Me
End Property
Note that while the GridCoord
class exposes a getter and a setter for both X
and Y
properties, the IGridCoord
interface only exposes the getters. As a result, code written against the IGridCoord
interface is effectively working with read-only properties.
Another use is to get the name of the class module, without needing to hard-code it. This is particularly useful when raising custom errors: just use TypeName(Me)
for the Source
of the error.
The Builder Pattern notoriously returns Me
, which enables a "fluent API" design that makes it possible to write code that incrementally builds complex objects through chained member calls, where each member returns Me
(except the final Build
call, which returns the type of the class being built):
Dim thing As Something
Set builder = New ThingBuilder
Set thing = builder _
.WithFoo(42) _
.WithBar("test") _
.WithSomething _
.WithSomethingElse
.Build
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With