Присвоение объектов в VB6 - PullRequest
26 голосов
/ 26 января 2011

Я пытаюсь создать два идентичных объекта в VB6 с помощью операторов присваивания;что-то вроде этого ...

Dim myobj1 As Class1
Dim myobj2 As Class1

Set myobj1 = New Class1
myobj1.myval = 1
Set myobj2 = myobj1

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

Set myobj2 = new Class1
myobj2.mem1 = myobj1.mem1
...

?

Edit 2 Скотт Уитлок обновил свой отличный ответ, и я включил его изменения в этот теперь работающий фрагмент кода.

Private Type MyMemento
     Value1 As Integer
     Value2 As String
End Type

Private Memento As MyMemento

Public Property Let myval(ByVal newval As Integer)
Memento.Value1 = newval
End Property

Public Property Get myval() As Integer
myval = Memento.Value1
End Property

Friend Property Let SetMemento(new_memento As MyMemento)
    Memento = new_memento
End Property

Public Function Copy() As Class1
     Dim Result As Class1
     Set Result = New Class1
     Result.SetMemento = Memento
     Set Copy = Result
End Function

Затем выполняется выполнение кода таким образом ...

Set mysecondobj = myfirstobj.Copy

Ответы [ 3 ]

38 голосов
/ 26 января 2011

Как и многие современные языки, VB6 имеет типы значений и ссылочные типы. Классы определяют ссылочные типы. С другой стороны, ваши базовые типы, такие как Integer, являются типами значений.

Основная разница в назначении:

Dim a as Integer
Dim b as Integer
a = 2
b = a
a = 1

В результате a равно 1, а b равно 2. Это потому, что присваивание в типах значений делает копию. Это связано с тем, что каждой переменной выделено место для значения в стеке (в случае VB6 целое число занимает в стеке 2 байта).

Для классов это работает иначе:

Dim a as MyClass
Dim b as MyClass
Set a = New MyClass
a.Value1 = 2
Set b = a
a.Value1 = 1

В результате оба значения a.Value1 и b.Value1 равны 1. Это потому, что состояние объекта хранится в куче, а не в стеке. В стеке хранится только ссылка на объект, поэтому Set b = a перезаписывает ссылку. Интересно, что VB6 явно говорит об этом, заставляя вас использовать ключевое слово Set. Большинство других современных языков не требуют этого.

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

Различия между классом и определяемым пользователем типом (кроме класса, являющегося ссылочным типом, и UDT, являющегося типом значения) заключается в том, что класс может содержать поведения (методы и свойства), в которых UDT не может. Если вы просто ищете класс типа записи, то UDT может быть вашим решением.

Вы можете использовать сочетание этих техник. Допустим, вам нужен класс, потому что у вас есть определенные поведения и расчеты, которые вы хотите включить в данные. Вы можете использовать шаблон memento для хранения состояния объекта внутри UDT:

Type MyMemento
    Value1 As Integer
    Value2 As String
End Type

В вашем классе убедитесь, что all ваше внутреннее состояние хранится внутри закрытого члена типа MyMemento. Напишите свои свойства и методы, чтобы они использовали данные только в этой закрытой переменной-члене.

Теперь сделать копию вашего объекта просто. Просто напишите в вашем классе новый метод с именем Copy(), который возвращает новый экземпляр вашего класса, и инициализируйте его копией собственного сувенира:

Private Memento As MyMemento

Friend Sub SetMemento(NewMemento As MyMemento)
    Memento = NewMemento
End Sub

Public Function Copy() as MyClass
    Dim Result as MyClass
    Set Result = new MyClass
    Call Result.SetMemento(Memento)
    Set Copy = Result
End Function

Friend скрывает его только от материалов, находящихся вне вашего проекта, поэтому скрывать сабвуфер SetMemento не так уж и много, но это все, что вы можете сделать с VB6.

НТН

3 голосов
/ 27 июня 2011

@ Скотт Уитлок, я не смог заставить ваш код работать, но если бы он работал, это было бы здорово.

Я создал обычный модуль, в который я помещаю тип сувенира

Type MyMemento
    Value1 As Integer
    Value2 As String
End Type

Затем я создаю модуль класса MyClass с кодом

Private Memento As MyMemento

Friend Sub SetMemento(NewMemento As MyMemento)
        Memento = NewMemento
End Sub

Public Function Copy() as MyClass
    Dim Result as MyClass
    Set Result = new MyClass
    Result.SetMemento(Memento)
    Set Copy = Result
End Function

Наконец, я пытаюсь вызвать функцию копирования в другом обычном модуле, подобном этому

Sub Pruebas()
    Dim Primero As MyClass, segundo As MyClass
    Set Primero = New MyClass
    Set segundo = New MyClass
    Set segundo = Primero.Copy
End Sub

Я получаю сообщение(под картинкой): Ошибка компиляции: типографский метод не совпадает

Вот изображение (если не считать 10 баллов, так вот ссылка): http://i.stack.imgur.com/KPdBR.gif

IЯ не смог получить сообщение на английском, я живу в Испании.

Не могли бы вы привести пример в VBA Excel? Я действительно пытался сделать эту работу.

Спасибо за вашу работу

==============================================

РЕДАКТИРОВАТЬ: проблема решена:

Проблема была в строке "Result.SetMemento (Memento)", в VBA ее нужно было вызывать с помощью "Call"

Public Function Copy() As MyClass
    Dim Result As MyClass
    Set Result = New MyClass
    Call Result.SetMemento(Memento)
    Set Copy = Result
End Function

Работает GreaТ, спасибо Скотт Уитлок, ты гений

2 голосов
/ 26 января 2011

или мне нужно копировать объект по одному элементу за раз ...

К сожалению, да.

Возможно (но технически очень очень сложно) написать COM-сервер на C ++, который - используя интерфейс IDispatch - скопирует значение каждого свойства, но на самом деле это Программирование Высокого Храма , если бы мне пришлось это сделать, я не знаю, смогу ли я сделать это, но я бы посмотрел на что-то вроде 10 дней работы (и я знаю, какCOM реализован на C ++, мне также нужно выяснить, есть ли у инфраструктуры ATL что-нибудь, что может помочь и т. Д.)

Я работал с Vb3, 4,5 и 6 около 10 лет (руки,5 дней в неделю) и никогда не находил хорошего способа сделать это, кроме ручной реализации шаблонов сериализации, таких как Mementos и Save & Store, которые на самом деле сводились к причудливым способам копирования каждого элемента, по одному за раз.

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