Die Herstellung einer direkten Kopie eines Objekts (eines so
genannten "Clones") in seinem aktuellen Zustand mitsamt
den Werten aller Eigenschaften und lokalen Variablen ist in Visual
Basic nicht vorgesehen. Es ist zwar ein leichtes, eine neue Instanz
eines Objekts (Klasse, Form usw.) anzulegen und die Werte der
öffentlich zugänglichen Eigenschaften einen nach der anderem
manuell aus dem Ursprungs-Objekt auszulesen und dem Clone
zuzuweisen. Aber den inneren Zustand eines Objekts, nämlich die
Werte der lokalen/privaten Variablen, können Sie so nicht
übertragen. Natürlich können Sie auch diese als Eigenschaften
zugänglich machen, wenn auch vielleicht nicht öffentlich.
Deklarieren sie diese als Friend, bleiben sie nach außen hin
verborgen, können aber intern innerhalb des Projekts verwendet
werden. Trotzdem hat das einen mitunter nicht unerheblichen
Code-Aufwand zur Folge, sowohl im betreffenden Objekt als auch dort,
wo die Kopie hergestellt werden soll.
Ab Visual Basic 6 können Sie jedoch zur Übertragung der Daten
von einem Objekt zu einem anderen eine frei anlegbare Instanz des PropertyBag-Objekts
verwenden (wie Sie das auch in VB 5 realisieren
können, zeige ich Ihnen weiter unten auch noch). Der Code-Aufwand
auf Seiten des Objekts reduziert sich zwar nicht allzu viel, der
Aufruf des Clone-Vorgangs selbst dagegen erheblich, nämlich auf
eine einzige Zeile.
Schauen wir uns einmal die folgende Beispiel anhand einer Klasse
("clsClass") an. Sie verfügt über eine öffentliche
Eigenschaft "Datum" und weiterhin eine private/lokale
Variable, die hier einfach einen im Prinzip beliebigen Long-Wert
enthält. Dazu bietet die Klasse die öffentliche Methode "Clone"
an, die als Funktionswert eine frischgebackene Kopie ihrer selbst
abliefert.
Dort wird zunächst eine Instanz des PropertyBag-Objekts
angelegt, die mit den aktuellen Werten der Eigenschaftenvariablen
pDatum und der privaten Variablen mClones gefüttert wird (mClones
stellt hier einen einfachen Zähler dar, der nachhält, wie viele
Clones von der aktuellen Instanz der Klasse produziert worden sind).
Dann wird eine neue Instanz der Klasse angelegt, der über die als
Friend deklarierte Methode CloneProperties das PropertyBag-Objekt
übergeben wird. Die neue Klassen-Instanz liest dort die Werte aus
dem PropertyBag-Objekt aus. Dann wird sie als Funktionswert an den
aufrufenden Code zurückgegeben.
Private mClones As Long
Private pDatum As Date
Public Property Get Datum() As Date
Datum = pDatum
End Property
Public Property Let Datum(ByVal New_Datum As Date)
pDatum = New_Datum
End Property
Public Function Clone() As clsClass
Dim nClone As clsClass
Dim nPropBag As PropertyBag
mClones = mClones + 1
Set nPropBag = New PropertyBag
nPropBag.WriteProperty "Datum", pDatum
nPropBag.WriteProperty "Clones", mClones
Set nClone = New clsClass
nClone.CloneProperties nPropBag
Set Clone = nClone
End Function
Friend Sub CloneProperties(PropBag As PropertyBag)
pDatum = PropBag.ReadProperty("Datum")
mClones = PropBag.ReadProperty("Clones")
Debug.Print "Ich bin Clone Nummer " & mClones
End Sub
Der aufrufende Code ist nun wirklich simpel - zum Beispiel in
einem Form:
Private mClass As clsClass
Private Sub cmdClone_Click()
Dim nClone As clsClass
Set nClone = mClass.Clone
End Sub
In Visual Basic 5 brauchen Sie eine eigene Nachbildung des
PropertyBag-Objekts, da Sie das VB-eigene PropertyBag-Objekt dort
noch nicht direkt instanzieren können. Wir können hier auf die
Serialisierung und die Übergabe von Standardwerten durchaus
verzichten. Daher genügt eine kleine Hüllklasse (Klassen-Name
"PropertyBag5") für eine Collection
- Sie brauchen nur die Deklarationen im obenstehenden Beispiel
entsprechend anzupassen. Beim Einlesen eines Wertes versuchen wir
einfach, den Wert an die interne Collection anzufügen - einen
Fehlschlag ignorieren wir mit einem On Error Resume Next (dies
entspricht auch dem Verhalten des originalen PropertyBag-Objekts).
Zum Auslesen eines Wertes versuchen wir zunächst, als Rückgabewert
ein Objekt aus der Collection zu erhalten - schlägt dies fehl,
versuchen wir es mit einem allgemeinen Variant-Datentyp. Schlägt
auch dies fehl, geben wir den Konstantwert vbEmpty zurück.
Private mValues As Collection
Public Sub WriteProperty(Key As String, Value As Variant)
On Error Resume Next
mValues.Add Value, Key
End Sub
Public Function ReadProperty(Key As String) As Variant
On Error Resume Next
Set ReadProperty = mValues(Key)
If Err.Number Then
Err.Clear
ReadProperty = mValues(Key)
If Err.Number Then
ReadProperty = vbEmpty
End If
End If
End Function
Private Sub Class_Initialize()
Set mValues = New Collection
End Sub
Private Sub Class_Terminate()
Set mValues = Nothing
End Sub

|