Наследование классов в VBA врукопашную

OMi
Дата: 12.11.2009 19:42:42
Это даже не вопрос, а приглашение к обсуждению.
Наследования в прямом смысле НЕТ, но можно обмануть железную дорогу и...
Иногда так хочется, или ОЧЕНЬ нужно.
Итак, Вариант 1:
Предок сам создает потомка. Это не по стандартам ООП, но мы же в Аксе.

Модуль класса mDoc - будущий предок

Option Compare Database
Option Explicit
'Предок сам создает потомка (нестандартный вариант)

Private FChild As Object 'Вероятный наследник (любого типа!!!!)

Private Sub Class_Terminate()
Set FChild = Nothing
Debug.Print "Уничтожили предка"
End Sub

Public Property Get mType() As String
If FChild Is Nothing Then
mType = TypeName(Me)
Else
mType = TypeName(FChild)
End If
End Property

Public Property Let mType(byType As String)
'Создать объект-потомок типа byType
If Not FChild Is Nothing Then Set FChild = Nothing
Set FChild = GetObjectByTypeName(byType)
If Not FChild Is Nothing Then Set FChild.Doc = Me
End Property

Private Function GetObjectByTypeName(byType As String) As Object
'Как образец
'Может быть внешней функцией
'Должна обеспечить, если сможет :) создание объекта-наследника конкретного типа
Select Case byType
Case "mDocChild": Set GetObjectByTypeName = New mDocChild
Case Else: Set GetObjectByTypeName = Nothing
End Select
End Function

Public Function OnlyParent() As String
'функция не перегруженная
OnlyParent = TypeName(Me)
End Function

Public Function OnlyParentOverload(Optional ext As Boolean = False) As String
'Функция перегружаемая потомком
'************************************************
'Параметр Optional ext As Boolean = False обязателен для перегружаемых методов
'ext необходим для предотвращения stack overflow при обратных вызовах
'Следующий код нужно тупо вставлять для всех перегружаемых методов
If ext Then GoTo selfCode
On Error GoTo selfCode
OnlyParentOverload = FChild.OnlyParentOverload
Exit Function
selfCode:
On Error GoTo 0
'************************************************
'Собственный код mDoc
OnlyParentOverload = "Из предка mDoc"
End Function
Модуль класса mDocChild - будущий потомок

Option Compare Database
Option Explicit
'Потомок mDoc с наследованием и перегрузкой методов

Public Doc As mDoc 'экземпляр класса предка

Public Function OnlyParentOverload() As String
'Функция перегруженная потомком
OnlyParentOverload = "Из потомка mDocChild " _
& "+ " & Doc.OnlyParentOverload(True)
End Function

Private Sub Class_Terminate()
Debug.Print "Уничтожили потомка"
End Sub
Использование всего этого безобразия. (В любом обычном модуле)

Public Sub testOverLoad()
Dim Doc As mDoc
Set Doc = New mDoc
Doc.mType = "mDocChild"
Debug.Print Doc.OnlyParent & " не перегружаемая"
Debug.Print Doc.OnlyParentOverload & " перегруженная"
Doc.mType = ""
Set Doc = Nothing
End Sub
Вариант 2:
Потомок создает предка. Это по стандартам ООП.
...... Продолжение в следующей серии :)
Бенедикт
Дата: 12.11.2009 22:14:41
OMi,

А где, собственно, постановка задачи, терминология, описание адресуемых проблем, и т. д.? Пока это не приглашение к обсуждению, а монолог.
старенький эх
Дата: 12.11.2009 23:42:02
Сферические кони уже проглядываются.
Осталось еще вакуум к ним подрисовать.

PS
потомок, создавший предка - это вам не белые дыры с ручками - этому даже любители современной астофизики позавидуют.
... эх
Дата: 12.11.2009 23:42:42
астрофизики
OMi (как Guest)
Дата: 13.11.2009 00:06:44
Бенедикт, прошу прощения, вошел черте знает откуда. Пароля с собой нет.
Дата последнего найденного мной обсуждения темы где-то 2004 год.
Аксесный народ, похоже мало интересуется этой темой на форумах. Или я плохо искал.
Точка приложения (из названий классов) - документ сообще и документы конкретные. Просто как родное ложится на наследование, а в Аксе нет. Ни кто ничего не пишет. Пришла в голову шальная мысль - вот поэтому и монолог.
Что смущает:
- Вся конструкция через On Error (exception). Слава Богу, есть гениальное On Error Resume Next.
Может можно как-то "по-хорошему", не через исключение?
- Есть такая ф-ция AdressOf (вроде так). Возвращает какой-то указатель. Вне Акс,понятно какой, а что это такое с точки зрения Акс? В принципе, что нужно? Объект есть, имя требуемого метода известно, указатель на метод (точка входа) есть. А как запустить?
- Есть еще возможность наследовать класс как интерфейс. Там свои законы, неудобно. Сам в VBA не пробовал, но народ в сети пишет,что работает.
Что обсуждать?
- Эта тема хоть кого-то интересует?
- Есть ли какие-то раскопки в этом направлении?
- Нет предела совершенству. Хочется, чтобы было удобнее, надежнее и красиво, в конце концов.

OMi (как Guest)
OMi (as Guest)
Дата: 13.11.2009 00:18:29
старенький эх,
Наверно,совсем старенький...
Когда формочку свою городишь, родную собственную, ведь она потомок некоего объекта Form.
При этом, еще, пользуешься interface этой самой Form. (не путать с лицом).
Почитай в Википедии (не путать с ...), что такое Объектно-Ориентированное Программирование (ООП).
старенький эх
Дата: 13.11.2009 00:54:35
OMi (as Guest)
старенький эх,
Наверно,совсем старенький...
Когда формочку свою городишь, родную собственную, ведь она потомок некоего объекта Form.
При этом, еще, пользуешься interface этой самой Form. (не путать с лицом).
Почитай в Википедии (не путать с ...), что такое Объектно-Ориентированное Программирование (ООП).

верно. совсем старенький.
Википедии читать - мне моих старых мозгов не хватит. я даже начинать не буду.
Подожду пока - вдруг ты мне своими собственными словами объяснишь, что это за зверь такой.
Особенно про то, как потомки порождают порождают предков.
(Попкорном я уже запасся)

Бенедикт тебе уже как бы намекнул, что в отсутсвии конкретной задачи, малек вне контекста словеса про "наследование".

Астронавт ты наш яхонтовый.

ЗЫ
по своей беспросветной старости подозреваю, что задача сведется к "хочу поднимать свою форму для строки таблицы, в зависимотси от того, чей она <потомок>".
Попкорна и на другие варианты хватит.
Бенедикт
Дата: 13.11.2009 01:23:40
OMi (как Guest),

уж ночь, чисто для затравки.
Класс CDoc:
Option Explicit

Public Function OnlyParentOverload() As String
 OnlyParentOverload = "CDoc::OnlyParentOverload()"
End Function
Класс CDocChild:
Option Explicit

Implements CDoc

Private m_CDoc As CDoc

Private Sub Class_Initialize()
 Set m_CDoc = New CDoc
End Sub

Private Function CDoc_OnlyParentOverload() As String
 CDoc_OnlyParentOverload = m_CDoc.OnlyParentOverload
End Function

Public Function OnlyParentOverload() As String
 OnlyParentOverload = "CDocChild::OnlyParentOverload()"
End Function
Вспомогательная функция в обычном модуле:
Public Function CDoc(ByVal Obj As Object) As CDoc
 Set CDoc = Obj
End Function
Тест:
Sub Test()
 Dim DocChild As CDocChild
 Set DocChild = New CDocChild
 Debug.Print DocChild.OnlyParentOverload
 Debug.Print CDoc(DocChild).OnlyParentOverload
End Sub
... эх
Дата: 13.11.2009 03:22:54
2 Бенедикт

(Раз уж это нехорошее слово - "наследование" - прозвучало)

Вероятно ты написал то, что ожидает увидеть топткстартер.
Однако, твой пример содержит ошибку, т.к. прямо противоречит пониманию наследования
в языках типа Java. Показанный тобой класс CDocChild не является наследником cDoc.

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

(Т.е. если на переменной супертипа отдать приказ "документу" - сохранись, или "отобразись"
будет как-то печально увидеть порезанную визуалку или обнаружить, что строка сохранилась
не в ту таблицу или были сохранены не все поля.)

Твой пример должен быть переписан таким оразом;

Класс CDocChild:

Option Explicit

Implements CDoc

Private m_CDoc As CDoc

Private Sub Class_Initialize()
 Set m_CDoc = New CDoc
End Sub

Private Function CDoc_OnlyParentOverload() As String
 CDoc_OnlyParentOverload = OnlyParentOverload 'm_CDoc.OnlyParentOverload
End Function

Public Function OnlyParentOverload() As String
 OnlyParentOverload = "CDocChild::OnlyParentOverload()"
End Function

Вот теперь мы имеем "честного" потомка в смысле приведения к типу предка.
Не надо учить людей плохому.
А так - сплошная красота и полный ООПздец.

PS
похоже, сайт был недоступен некоторое время.