PBe*_*ezy 5 oop excel vba class
这两个 sub 在一个类中做同样的事情。
Sub DemoMe( )
Me.AboutMe ' Calls AboutMe procedure.
End Sub
Sub DemoMe( )
AboutMe ' Does the same thing.
End Sub
Run Code Online (Sandbox Code Playgroud)
重点是什么?Me 关键字有什么作用吗?对象访问其自身成员的首选方式是什么?
tldr; 不,尽管在某些情况下它可能有用。
来自 VBA 语言规范 ( 5.3.1.5 ):
作为方法的每个过程都有一个隐式 ByVal 参数,称为当前对象,该对象对应于方法调用的目标对象。当前对象充当具有过程范围的匿名局部变量,其声明的类型是包含方法声明的类模块的类名。在方法激活的持续时间内,当前对象变量的数据值是创建该激活的过程调用的目标对象。当前对象使用方法的 <procedure-body> 中的Me关键字访问 ,但不能分配给或以其他方式修改。
这就是全部,只是一个“自由”局部变量,它指的是正在调用该方法的特定实例。这也恰好是过程调用期间的默认上下文,因此如果代码旨在对当前实例进行操作,则可以省略它。尽管正如@HansPassant 在上面的评论中指出的那样,它也允许编辑器绑定到界面并提供 IntelliSense。
也就是说,在某些情况下,您可能想要或必须使用它(这绝不是一个详尽的列表):
命名冲突:
如果您的类具有“隐藏”内置 VBA 函数的成员,则可以使用它来明确作用域:
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
Run Code Online (Sandbox Code Playgroud)
股权检查:
Public Function Equals(other As Object) As Boolean
If other Is Me Then
Equals = True
Exit Function
End If
'...
End Function
Run Code Online (Sandbox Code Playgroud)
流畅的功能:
这对于合成对象来说是一个有用的模式——你执行一个动作,然后返回类的实例,这样它们就可以被“链接”起来。Excel 的Range界面在很多情况下都会这样做:
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
Run Code Online (Sandbox Code Playgroud)
没有什么比this在 Java、C# 或任何其他语言中使用更多的理由:它是一个保留的标识符,代表类的当前实例——你用它做什么取决于你的想象。
对象访问其自身成员的首选方式是什么?
事实上,对象并不需要在Me访问它自己的公共接口关键字。与this其他语言一样,我什至认为它是多余的。然而,有时使用 显式限定成员调用可能是一个好主意Me,尤其是当类具有VB_PredeclaredId属性(例如 any UserForm)时:UserForm1在代码隐藏中UserForm1引用产生对类的默认实例的引用,而限定成员调用withMe产生对该类的当前实例的引用。
访问继承成员
VBA用户代码不能做的类继承,但很多VBA类做有一个基类。的成员UserForm,当你在代码隐藏的UserForm1,和那些Worksheet当你在代码隐藏的Sheet1,不一定容易找到。但由于继承的成员显示在IntelliSense /auto-complete 中,您可以键入Me.并浏览从基类继承的成员列表,否则您需要了解这些成员才能调用。
一个在自身内部创建自身实例的类?我从未见过的。
你错过了!我一直这样做,以便能够With在工厂方法中引用块持有的对象实例- 就像这个 GridCoord 类。
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
Run Code Online (Sandbox Code Playgroud)
请注意,虽然GridCoord该类为X和Y属性公开了一个 getter 和一个 setter,但该IGridCoord接口只公开了 getter。因此,针对IGridCoord接口编写的代码可以有效地使用只读属性。
另一个用途是获取类模块的名称,而无需对其进行硬编码。这在引发自定义错误时特别有用:仅TypeName(Me)用于Source错误。
所述生成器模式众所周知的回报Me,这使得一个“流利API”的设计,使得可以写入代码,递增地建立通过链接的部件的呼叫复杂对象,每个构件返回其中Me(除了最后的Build呼叫时,它返回类的类型被建):
Dim thing As Something
Set builder = New ThingBuilder
Set thing = builder _
.WithFoo(42) _
.WithBar("test") _
.WithSomething _
.WithSomethingElse
.Build
Run Code Online (Sandbox Code Playgroud)