在VB6中分配对象
我试图通过赋值语句在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 Scott Whitlock已经更新了他的优秀答案,并且将他的更改纳入了这个现在可用的代码片段。
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
与许多现代语言一样,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
子,但这是VB6所能做的。
HTH
+1 Cleanest Memento实现我在VBx中看到过,我从来没有考虑过使用类型作为快捷方式。干得好那个男人! – 2011-01-26 14:49:32
@Binary Worrier - 谢谢!我知道我的l33t VB6技能有一天会派上用场......哈哈。 :) – 2011-01-26 15:20:28
或我必须一个成员复制的对象以时间...
不幸的是。
这是可能的(但技术上非常非常困难)用C写一个COM服务器++是 - 使用IDispatch接口 - 将复制每个属性的值,但实际上这是高寺编程,如果我必须这样做,我不知道如果我可以做到这一点,但我会看看像10天的工作(我知道COM是如何在C++中实现的,我还需要调查看看ATL框架是否有任何帮助等)。
我Vb3的工作,4,5 & 6类似10年(双手,每周5天),并没有找到一个很好的办法做到这一点,除了手动实现序列化模式,如纪念品和保存&商店,这实际上只是简单地复制每个成员的复制方式,一次一个。
@Scott惠特洛克,我不能让你的代码的工作,但如果它的工作原理是将是巨大的。
我创建了一个常规的模块,我把纪念型
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
我收到消息(下图):Error de compi lacion:萨尔瓦多TIPO德agumento德为ByRef没有重合
这里是一个图像(达到10点,因此这里是链接):http://i.stack.imgur.com/KPdBR.gif
我是不是能够用英语得到的消息,我在西班牙生活。
您是否愿意在VBA Excel中提供一个示例?我一直在努力做到这一点。
谢谢你的工作
====================================== =========
编辑:问题就迎刃而解了:
问题是上线 “Result.SetMemento(记忆碎片)”,在VBA它需要与被称为 “呼叫”
Public Function Copy() As MyClass
Dim Result As MyClass
Set Result = New MyClass
Call Result.SetMemento(Memento)
Set Copy = Result
End Function
它很好用,谢谢Scott Whitlock,你是个天才
这个问题可能是有趣的:http://stackoverflow.com/questions/218696/cloning-objects-in-vba – 2011-01-26 14:29:07