Давно заметил некоторый глюк при использовании Property (GET/SET) вместо методов или функций. Наконец-то добрался изучить материал более точно.
Первичный диагноз: при использовании в кач-ве значения Property пользовательский класс (Custom Class), компилятор теряет доступ к видимости методов, функций и свойств этого самого класса и выдает ошибку: Variable not declared: <Имя-вызываемой-процедуры>
Google не дал какой-то полезной информации (а может плохо искал?), идем проводить эксперименты...
Исходные данные:
Тестовая среда: 8.5.3 FP3
Класс А. Метод, функция и свойство - пустые, нам надо всего лишь проверить, что их видит компилятор
Class ClassA
Sub New()
End Sub
Public Sub SomeSub()
End Sub
Public Function SomeFunc() As String
End Function
Public Property Get SomeProp As String
End Property
End Class
Класс B. В качестве одного из своих свойств возвращает экземпляр класса А. Сначала объявим только свойство Get
Class ClassB
Private pr_classA As ClassA
Sub New()
End Sub
Public Property Get ClassA As ClassA
If pr_ClassA Is Nothing Then Set pr_ClassA = New ClassA
Set ClassA = pr_ClassA
End Property
End Class
Тест 1.
Добавим процедуру, вызывающую ClassA.SomeFunc() через класс B
Sub Test()
Dim classB As New ClassB
MsgBox classB.ClassA.SomeFunc()
End Sub
Итог: Тест пройден успешно, компилятор не ругается
Тест 2.
Добавим класс, вызывающий ClassA.SomeFunc() через класс B
Class MainClass
Sub New()
Dim classB As New ClassB
MsgBox classB.ClassA.SomeFunc()
End Sub
End Class
По сравнению с предыдущим тестом по-сути ничего не изменилось. Лишь вызов происходит не из самостоятельной процедуры, а внутри метода некоторого класса. И тут мы получаем: Variable not declared: SOMEFUNC. Нипоняяятно. Понятно, что если подставить метод или свойство класса А ничего не изменится.
Итог: Тест провален, получили ошибку компиляции
Тест 3.
Не меняя кода класса MainClass (тестового класса), добавим в класс B свойство Set следующего содержания (можно было даже пустое...):
Public Property Set ClassA As ClassA
Set pr_ClassA = ClassA
End Property
И, о чудо! Ошибка пропала...
Итог: Тест пройден. Если добавить пару Get/Set - все ок.
Тест 4.
В классе B удаляем свойство Set
Добавляем в класс MainClass:
Dim classA As ClassA
Set classA = classB.ClassA
Call classA.SomeSub()
Итог: Тест пройден. Ошибок нет. Если добавить промежуточную переменную, содержащую экземпляр класса А, который возвращает класс В - ошибки не возникает.
Итого:
1. Если нужно возвращать типизированный результат через свойство класса Get (и возвращаемый тип - экземпляр пользовательского класса), нужно использовать парное ему свойство Set
2. Лучше для таких случаев (когда возвращаем пользовательский класс) все же использовать GetClassA() as ClassA (и SetClassA(a as ClassA)).
P.S. Мне казалось, что на практике встречал и более изощренные случаи, когда ошибка возникала и для методов класса, возвращающих пользовательский класс. Сходу воспроизвести не смог, но понаблюдаю еще и постараюсь не забыть зафиксировать, если наткнусь
P.P.S. Буду признателен, если укажите, где я ошибся в рассуждениях или приведете подтверждающие и расширяющие примеры.
Первичный диагноз: при использовании в кач-ве значения Property пользовательский класс (Custom Class), компилятор теряет доступ к видимости методов, функций и свойств этого самого класса и выдает ошибку: Variable not declared: <Имя-вызываемой-процедуры>
Google не дал какой-то полезной информации (а может плохо искал?), идем проводить эксперименты...
Исходные данные:
Тестовая среда: 8.5.3 FP3
Класс А. Метод, функция и свойство - пустые, нам надо всего лишь проверить, что их видит компилятор
Class ClassA
Sub New()
End Sub
Public Sub SomeSub()
End Sub
Public Function SomeFunc() As String
End Function
Public Property Get SomeProp As String
End Property
End Class
Класс B. В качестве одного из своих свойств возвращает экземпляр класса А. Сначала объявим только свойство Get
Class ClassB
Private pr_classA As ClassA
Sub New()
End Sub
Public Property Get ClassA As ClassA
If pr_ClassA Is Nothing Then Set pr_ClassA = New ClassA
Set ClassA = pr_ClassA
End Property
End Class
Тест 1.
Добавим процедуру, вызывающую ClassA.SomeFunc() через класс B
Sub Test()
Dim classB As New ClassB
MsgBox classB.ClassA.SomeFunc()
End Sub
Итог: Тест пройден успешно, компилятор не ругается
Тест 2.
Добавим класс, вызывающий ClassA.SomeFunc() через класс B
Class MainClass
Sub New()
Dim classB As New ClassB
MsgBox classB.ClassA.SomeFunc()
End Sub
End Class
По сравнению с предыдущим тестом по-сути ничего не изменилось. Лишь вызов происходит не из самостоятельной процедуры, а внутри метода некоторого класса. И тут мы получаем: Variable not declared: SOMEFUNC. Нипоняяятно. Понятно, что если подставить метод или свойство класса А ничего не изменится.
Итог: Тест провален, получили ошибку компиляции
Тест 3.
Не меняя кода класса MainClass (тестового класса), добавим в класс B свойство Set следующего содержания (можно было даже пустое...):
Public Property Set ClassA As ClassA
Set pr_ClassA = ClassA
End Property
И, о чудо! Ошибка пропала...
Итог: Тест пройден. Если добавить пару Get/Set - все ок.
Тест 4.
В классе B удаляем свойство Set
Добавляем в класс MainClass:
Dim classA As ClassA
Set classA = classB.ClassA
Call classA.SomeSub()
Итог: Тест пройден. Ошибок нет. Если добавить промежуточную переменную, содержащую экземпляр класса А, который возвращает класс В - ошибки не возникает.
Итого:
1. Если нужно возвращать типизированный результат через свойство класса Get (и возвращаемый тип - экземпляр пользовательского класса), нужно использовать парное ему свойство Set
2. Лучше для таких случаев (когда возвращаем пользовательский класс) все же использовать GetClassA() as ClassA (и SetClassA(a as ClassA)).
P.S. Мне казалось, что на практике встречал и более изощренные случаи, когда ошибка возникала и для методов класса, возвращающих пользовательский класс. Сходу воспроизвести не смог, но понаблюдаю еще и постараюсь не забыть зафиксировать, если наткнусь
P.P.S. Буду признателен, если укажите, где я ошибся в рассуждениях или приведете подтверждающие и расширяющие примеры.
Комментарии
Отправить комментарий