Наследство VBA, аналог супер - PullRequest
       24

Наследство VBA, аналог супер

15 голосов
/ 08 сентября 2010

Например, у меня есть класс A, который реализует класс B

--- класс А ----

implements B
public sub B_do()
end sub

- класс B ----

public sub do()
end sub

Как я могу вызвать do () из A? (super.do ()) Итак, как я могу определить некоторые общие переменные для обоих классов? Теперь я могу наследовать только функции, подпрограммы и свойства ...

добавлено: тот же вопрос http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/5a83d794-3da1-466a-83d3-5d2eb0a054b2

добавлено: Невозможно совместно использовать переменную в иерархии классов. Вы должны реализовать свойство (так же, как функции).

Ответы [ 3 ]

22 голосов
/ 09 сентября 2010

Обычный способ сделать это в VBA состоит в том, чтобы A содержал экземпляр B, а также имел интерфейс A, реализующий интерфейс B, а затем делегировал вызовы интерфейса B A внутреннему B.

Это старый материал, но см. Руководство для программиста Visual Studio 6.0:

http://msdn.microsoft.com/en-us/library/aa716285(VS.60).aspx

Существует глава «Много (меж) граней повторного использования кода», которая описывает это соглашение:

http://msdn.microsoft.com/en-us/library/aa240846(v=VS.60).aspx

MS описывает это так:

В дополнение к реализации абстрактных интерфейсов, вы можете повторно использовать свой код, реализуя интерфейс обычногоclass, а затем выборочное делегирование скрытому экземпляру класса.

Это означает, что для реализации наследования требуется множество явных методов делегирования.Есть даже подзаголовок главы: «Разве это не утомительно?».Еще одна причина, по которой ООП в VBA - это PITA (TM) ...

РЕДАКТИРОВАТЬ, ЧТО НЕ УКАЗАН В КОММЕНТАРИИ:

Чтобы ответить на вопрос, который вы задали в своем комментарии,A - это a B. Когда вы делаете A реализующим интерфейс B, вы, по сути, говорите, что можете рассматривать экземпляр A так, как если бы он действительно имел тип B. В VBA способ, которым вы это делаете,объявив переменную типа B, а затем присвоив ей экземпляр A. VBA узнает, что делать, когда вы называете ее как B:

Dim usedAsB as B
Dim anA as A

Set anA = New A
Set usedAsB = anA    'fine since A implements B

usedAsB.something()    'will call B_something() defined in class A

Насколько вы видите в отладкеокно, я не понимаю, почему это так выглядит.А что касается принудительного делегирования, я не уверен, что вы имеете в виду.VBA автоматически отправляет вызовы интерфейса B нужным методам в классе A.Если вы имеете в виду автоматическую генерацию кода для наследования реализации B способом, описанным выше, я не знаю ничего подобного для VBA.Я думаю, что различные «профессиональные» версии VB6 могли бы сделать это, но я никогда не использовал VB6, поэтому я не знаю.

1 голос
/ 03 января 2019

Так я долгое время использовал его для симуляции абстрактного класса через интерфейс.

'class module: IBase
'We define a base interface
'
Sub go(): End Sub

Sub gogo(): End Sub

Теперь давайте определим другие классы, начиная с абстрактного класса 'B'.

'
'class module: B
'
Implements IBase

'Daughter classes should implement 'go'
'Note that the method is 'Public'
Public Sub go(): End Sub

'Let's agree that every daughter class implements the method
'abstract 'super' that returns the IBase interface
Public Property Get super() As IBase: End Property

'
'The signature of other abstract methods can be stated here
'
'Public Sub goGoChild(): End Sub
'Public Function goGoGoChild2(): End Function
'

'
'Note that the methods are accessible through the IBase interface
'
Private Sub IBase_go()
    Debug.Print "B: super.go()"
End Sub

Private Sub IBase_gogo()
    Debug.Print "B: super.gogo()"
End Sub

Давайте создадим класс 'A', который реализует абстрактный класс 'B'

'
'class module: 'A'
'

'We started implementing the abstract class B
Implements B

'we define a private type 'myType'
Private Type myType

    'variable that references an instance of 'B'
    objB As B

    'variable that references the interface of 'B'
    objIB As IBase

End Type

'VBA version of 'this'
Private this As myType

'
'Every class that implements 'B' (abstract class)
'you must initialize in your constructor some variables
'of instance.
'
Private Sub Class_Initialize()

    With this

        'we create an instance of object B
        Set .objB = New B

        'the variable 'objIB' refers to the IBase interface, implemented by class B
        Set .objIB = .objB

    End With

End Sub


'Visible only for those who reference interface B
Private Property Get B_super() As IBase

    'returns the methods implemented by 'B', through the interface IBase
    Set B_super = this.objIB

End Property

Private Sub B_go()
    Debug.Print "A: go()"
End Sub
'==================================================

'Class 'A' local method
Sub localMethod1()
    Debug.Print "A: Local method 1"
End Sub

И, наконец, давайте создадим модуль 'main'.

Sub testA()

    'reference to class 'A'
    Dim objA As A

    'reference to interface 'B'
    Dim objIA As B

    'we create an instance of 'A'
    Set objA = New A

    'we access the local methods of instance 'A'
    objA.localMethod1

    'we obtain the reference to interface B (abstract class) implemented by 'A'
    Set objIA = objA

    'we access the 'go' method, implemented by interface 'B'
    objIA.go

    'we go to the 'go' method of the super class
    objIA.super.go

    'we access the 'gogo' method of the super class
    objIA.super.gogo

End Sub

И вывод в окне проверки будет:

A: Local method 1
A: go()
B: super.go()
B: super.gogo()

enter image description here

1 голос
/ 11 декабря 2018

Можно подделать трюк, чтобы подражать наследству.Он работает с использованием свойства элемента по умолчанию.

Если вы даете своему производному классу свойство Super с типом суперкласс, то сделайте его элементом по умолчанию (экспортируя и редактируя файл, включающий Attribute Item.VB_UserMemId = 0, повторноимпорт), тогда вы можете добраться до суперкласса просто парой круглых скобок (что разрешает член по умолчанию).

Это сообщение в блоге дает полную информацию, но автор (раскрытие, я) там использует 'Base' вместо 'Super'

Надеюсь, что синтаксис достаточно жесткий для вас,

Я также отмечаю, что это не раскрывает все внутренние силы базового класса, как в C #.Это означает, что мой метод не страдает от проблемы хрупкого базового класса.Т.е. мой метод сохраняет инкапсуляцию, что делает его лучше ИМХО.

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