Обнаруживается ли нарушение в VBA?

Скажите, что у вас есть этот код в модуле с именем Module1:

Option Explicit

Private Type TSomething
    Foo As Integer
    Bar As Integer
End Type

Public Something As TSomething

В эквивалентном С# -коде, если вы сделали поле Something public, код больше не будет компилироваться из-за несогласованной доступности - тип поля менее доступен, чем само поле. Что имеет смысл.

Однако в VBA вы можете иметь этот код в Module2:

Sub DoSomething()
    Module1.Something.Bar = 42
    Debug.Print Module1.Something.Bar
End Sub

И вы получаете IntelliSense при вводе его, и он компилируется, и он запускается, и он выводит 42.

Почему? Как это работает, с точки зрения COM? Является ли это частью спецификации языка?

Ответ 1

В соответствии с моим комментарием VBA предоставляет закрытый тип, так же как он предоставляет частное перечисление.

VBA предполагает, что вы можете использовать TypeInfo в контексте потребления, но он не позволит вам объявлять или создавать экземпляры этих типов или перечислений.

Этот ответ С++ является частично информативным:

Контроль доступа применяется к именам

Спецификатор доступа для имени не имеет ничего общего с типом

Но, возможно, полезно подумать о Private Type в стандартном модуле, что-то вроде класса PublicNotCreatable. Если вы предоставляете общедоступную оболочку, то тип доступен вне хост-модуля.

Но VBA обрабатывает вещи по-разному, когда Type находится в модуле общедоступного класса!

Здесь ваш Module1 расширен:

Option Explicit

Private Type TSomething
    Foo As Integer
    Bar As Integer
End Type

Public Type TOtherThing
    Foo As Integer
    Bar As Integer
End Type

Public Type TWrapperThing
  Something As TSomething
End Type

Public Something As TSomething
Public Otherthing As TOtherThing
Public Wrapperthing As TWrapperThing

Public Function GetSomething() As TSomething
  GetSomething.Foo = 1
End Function

Public Function GetOtherthing() As TOtherThing
  GetOtherthing.Foo = 1
End Function

И Module2 расширен:

Option Explicit

Sub DoThings()

'Compile Error: User-defined type not defined
  'Dim oSomething As TSomething
  Dim vSomething As Variant

  Dim oOtherthing As Module1.TOtherThing
  Dim vOtherthing As Variant
  Dim oWrapperthing As Module1.TWrapperThing

  Module1.Something.Foo = 42
  Module1.Otherthing.Foo = 42
  Module1.Wrapperthing.Something.Foo = 42

  'Compile Error: Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions
  'vSomething = Module1.Something
  'vOtherthing = Module1.Otherthing

  oOtherthing = Module1.Otherthing
  oOtherthing.Foo = 43

  'Is 43 > 42?
  Debug.Assert oOtherthing.Foo > Module1.Otherthing.Foo

'Compile Errors: "GetSomething" User-defined type not defined
  'Module1.GetSomething.Foo = 42
  'Module1.GetSomething().Foo = 42

  Module1.GetOtherthing.Foo = 42
  Module1.GetOtherthing().Foo = 42

End Sub