我试图通过赋值语句在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
答案 0 :(得分:38)
与许多现代语言一样,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中,它们被称为用户定义类型,但在大多数其他语言中,它们被称为结构或结构)。这是一个tutorial。
类和用户定义类型之间的差异(除了作为引用类型的类和作为值类型的UDT)是一个类可以包含UDT不能的行为(方法和属性)。如果您只是在寻找记录类型,那么UDT可能就是您的解决方案。
您可以混合使用这些技巧。假设您需要一个类,因为您希望包含某些行为和计算以及数据。您可以使用memento 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
sub并没有太大作用,但是你可以用VB6做些什么。
HTH
答案 1 :(得分:3)
@Scott Whitlock,我无法使你的代码工作,但如果它有效,那就太棒了。
我已经创建了一个常规模块,我将其放入纪念品类型
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 no coincide
这是一张图片(缺少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
它很棒,感谢Scott Whitlock,你是个天才
答案 2 :(得分:2)
或者我是否必须一次复制一个成员...
不幸的是,是的。
有可能(但在技术上非常非常很难)用C ++编写COM服务器 - 使用IDispatch接口 - 将复制每个属性的值,但实际上这是高寺庙编程,如果我必须这样做,我不知道我是否可以这样做,但我会看到像10天工作的东西(我知道如何COM是用C ++实现的,我还需要调查看看ATL框架是否有任何帮助等等。
我曾与Vb3,4,5&虽然手动实现Mementos和Save& amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp;商店,这真的只是简单地模仿复制每个成员的方式,一次一个。