Нужно ли мне ключевое слово Me в модулях класса? - PullRequest
0 голосов
/ 26 февраля 2019

Эти две субмарины делают одно и то же, когда находятся внутри класса.

Sub DemoMe( )
    Me.AboutMe    ' Calls AboutMe procedure.
End Sub

Sub DemoMe( )
    AboutMe    ' Does the same thing.
End Sub

Какой смысл?Ключевое слово Me делает что-нибудь?Каков предпочтительный способ доступа объекта к его собственным членам?

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

tldr; Нет, хотя бывают ситуации, когда это может быть полезно.


Из спецификации языка VBA ( 5.3.1.5 ):

Каждая процедура, которая является методом, имеет неявный параметр ByVal, называемый текущий объект , который соответствует целевому объекту вызова метода.Текущий объект действует как анонимная локальная переменная с процедурным экстентом, и объявленный тип которого является именем класса модуля класса, содержащего объявление метода.На время активации метода значение данных текущей переменной объекта является целевым объектом вызова процедуры, которая создала эту активацию.Доступ к текущему объекту осуществляется с помощью ключевого слова 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

Проверка эквити:

Public Function Equals(other As Object) As Boolean
    If other Is Me Then
        Equals = True
        Exit Function
    End If
    '...
End Function

Свободные функции:

Это может быть полезным шаблоном для компоновки объектов - вы выполняете действие, а затем возвращаете экземпляр класса, чтобы они могли быть «сцеплены».Интерфейс 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
0 голосов
/ 26 февраля 2019

Не более чем есть причины использовать this в Java, C # или любом другом языке: это зарезервированный идентификатор, который представляет текущий экземпляр класса - что вы делаете с этим, зависит от вашего воображения.

Каков предпочтительный способ доступа объекта к его собственным членам?

Действительно, объекту не нужно ключевое слово Me для доступа к своему общедоступному интерфейсу.То же, что и this на других языках, я бы даже назвал это избыточным.Однако иногда может быть хорошей идеей явно квалифицировать вызовы членов с помощью Me, особенно когда у класса есть атрибут VB_PredeclaredId (например, любой UserForm): ссылка на UserForm1 в коде позади UserForm1возвращает ссылку на экземпляр по умолчанию класса, тогда как квалифицированный член вызывает с Me, возвращает ссылку на текущий экземпляр этого класса.

Доступ к унаследованным членам

Код пользователя VBA не может выполнять наследование классов, но многие классы VBA do имеют базовый класс.Члены UserForm, когда вы находитесь в коде позади UserForm1, и члены Worksheet, когда вы находитесь в коде позади Sheet1, не всегда легко найти.Но поскольку унаследованные члены отображаются в IntelliSense / auto-complete, вы можете набрать Me. и просмотреть список членов, унаследованных от базового класса, членов, о которых в противном случае вам нужно было бы знать, чтобыinvoke.

Класс, создающий экземпляр себя внутри себя?То, что я никогда не видел.

Вы пропускаете!Я делаю это все время, чтобы включить ссылку на экземпляр объекта, содержащийся в блоке With, внутри Factory Method - как этот класс 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

Обратите внимание, что в то время как класс GridCoord предоставляет геттер и сеттер для свойств X и Y, интерфейс IGridCoord предоставляет только геттеры.В результате код, написанный для интерфейса IGridCoord, эффективно работает со свойствами, доступными только для чтения.

Другим способом является получение имени модуля класса без необходимости его жесткого кодирования.Это особенно полезно при возникновении пользовательских ошибок: просто используйте TypeName(Me) для Source ошибки.


Pattern Builder , как известно, возвращает Me, что позволяетКонструкция «плавного API», которая позволяет писать код, который постепенно создает сложные объекты через цепочечные вызовы членов, где каждый член возвращает Me (кроме заключительного вызова Build, который возвращает тип создаваемого класса):

Dim thing As Something
Set builder = New ThingBuilder
Set thing = builder _
    .WithFoo(42) _
    .WithBar("test") _
    .WithSomething _
    .WithSomethingElse
    .Build
0 голосов
/ 26 февраля 2019

@ PBeezy: В дополнение к моему комментарию:

Me относится к объекту, из которого он исходит, поэтому AboutMe находится в классе.Если у вас есть другой экземпляр, скажем, это Class1, у вас будет dim c как Class1, как только вы создадите экземпляр Class1 в Class1, вам нужно сообщить компилятору, какой класс вы используете, класс хранения или экземплярсозданный в, где me.class1.aboutme будет логически действительным.Вы также можете создать класс для каждой ячейки в рабочей книге, а затем сослаться на класс А1 из класса В1.Кроме того, если есть открытая функция / подпрограмма с именем AboutMe, это также помогает.

Класс (clsPerson)

Public c1 As clsPerson
Public strPersonName As String

Public Function NAME_THIS_PERSON(strName As String)
    strPersonName = strName
End Function

Public Function ADD_NEW_CHILD(strChildName As String)
    Set c1 = New clsPerson
    c1.strPersonName = strChildName
End Function

Обычный модуль

Sub test()

Dim c As New clsPerson

c.NAME_THIS_PERSON "Mother"
c.ADD_NEW_CHILD "Nathan"

Debug.Print c.strPersonName
Debug.Print c.c1.strPersonName

End Sub

Дает эти результаты

Mother
Nathan
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...