Подтвердить что ты не робот

Назначение объектов в VB6

Я пытаюсь создать два идентичных объекта в 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
...

?

Изменить 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
4b9b3361

Ответ 1

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

Основное отличие заключается в назначении:

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

В результате a равно 1 и b равно 2. Это потому, что присваивание в типах значений создает копию. Это потому, что каждая переменная имеет пространство, выделенное для значения в стеке (в случае VB6, Integer занимает 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 они называются User Defined Types, но на большинстве других языков они называются структурами или структурами). Здесь tutorial.

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

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

Type MyMemento
    Value1 As Integer
    Value2 As String
End Type

В своем классе убедитесь, что все ваше внутреннее состояние хранится внутри частного члена типа 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.

НТН

Ответ 2

@Scott Whitlock, я не смог заставить ваш код работать, но если он будет работать, это будет здорово.

Я создал регулярный модуль, где я помещаю тип memment

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

Я получаю сообщение (под рисунком): Ошибка компиляции: El tipo de agumento de ByRef не совпадает

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

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

Не могли бы вы предоставить пример в 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

Он отлично работает, благодаря Скотту Уитлоку, вы гений.

Ответ 3

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

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

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

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