При реализации интерфейса в VBA должны ли реализованные функции быть частными или публичными c? - PullRequest
3 голосов
/ 17 июня 2020

Я читаю о создании фабрик классов здесь: https://rubberduckvba.wordpress.com/2018/04/24/factories-parameterized-object-initialization/, и я не понимаю, почему они делают реализованные функции закрытыми, разве мы не хотели бы, чтобы они были publi c, чтобы мы могли получить к ним доступ?

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "Something"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Type TSomething
    Bar As Long
    Ducky As String
End Type

Private this As TSomething
Implements ISomething

Public Function Create(ByVal initialBar As Long, ByVal initialDucky As String) As ISomething
    With New Something
        .Bar = initialBar
        .Ducky = initialDucky
        Set Create = .Self
    End With
End Function

Public Property Get Self() As ISomething
    Set Self = Me
End Property

Public Property Get Bar() As Long
    Bar = this.Bar
End Property

Friend Property Let Bar(ByVal value As Long)
    this.Bar = value
End Property

Public Property Get Ducky() As String
    Ducky = this.Ducky
End Property

Friend Property Let Ducky(ByVal value As String)
    this.Ducky = value
End Property

Private Property Get ISomething_Bar() As Long
    ISomething_Bar = Bar
End Property

Private Property Get ISomething_Ducky() As String
    ISomething_Ducky = Ducky
End Property

Кроме того, почему вам нужно предоставлять свойства get и let для переменных publi c в интерфейсе?

1 Ответ

6 голосов
/ 17 июня 2020

Они должны быть Private.

Причина в том, что интерфейсы работают в VBA: члены Public модуля класса определяют его интерфейс по умолчанию . Это означает, что члены publi c из Class1 определяют, какие члены Class2 должны реализовать, если он Implements Class1.

Итак, если вы создаете Class1_DoSomething publi c, то вы раскрываете это в интерфейсе по умолчанию Class2, и это ... совсем не красиво.

Какой интерфейс вы используете для доступа к объекту, определяется тем, как вы его объявляете.

Dim thing As Class1
Set thing = New Class1

Если thing равно или реализует Class1, то код после этого объявления может вызывать все члены, представленные интерфейсом по умолчанию Class1 (т.е. его члены publi c).

Если Class1 реализует ISomething, и мы объявляем это следующим образом:

Dim thing As ISomething
Set thing = New Class1

Теперь элементы, с которыми мы можем работать, - это члены, определенные членами publi c из ISomething класс / интерфейс.

Когда вы реализуете интерфейс или обрабатываете события, вы никогда не должны вручную вводить подписи; вместо этого выберите интерфейс (или поставщик событий) в верхнем левом раскрывающемся списке на панели кода, затем выберите член из раскрывающегося списка в правом верхнем углу: VBE автоматически создает правильную процедуру с правильной подписью, и она всегда будет член Private - эмпирическое правило, все, что имеет подчеркивание в своем имени в VBA, не имеет отношения к Public


Что касается того, почему вы должны предоставить Get и Let аксессоры для того, что вы определили как поле publi c (/ variable) в классе интерфейса ... Поля - это детали реализации, они никогда не должны быть Public в первую очередь. Объекты предоставляют свойства , а не поля - сохраняйте поля для частного внутреннего состояния реализующего класса.

Причина техническая: код VBA компилируется в библиотеку типов COM, и эта библиотека видит ваша переменная publi c и говорит, что "это должны быть методы PUT и GET", а код VBA, реализующий этот интерфейс, поэтому должен реализовать свойство для каждого поля publi c, потому что поля publi c скомпилировать до свойств.

Это имеет интересные последствия в отношении практики раскрытия поля publi c в модуле класса (в любом случае прерывает инкапсуляцию по сравнению с компиляцией до свойства!), но это все другое обсуждение.

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