Hilfreiche Introvertiertheit

Ein Problem, das sich bei vielen Klassen und ihren Instanzen immer wieder stellt, ist das des Kopierens eines komplexen Objekts. Man wird da leicht vom Operator „=“ in die Irre geführt.

Nehmen wir mal an, wir haben eine Klasse Tier.
Diese besitzt zwei Eigenschaften (für Anglophile: Properties) der Art String, nämlich Art und Laut.

Im Run- oder Open-Event der Anwendung erstelle ich eine neue Tier-Instanz:

Dim Tier1 As New Tier
Tier1.Art = "Hund"
Tier1.Laut = "Wuff"

Die Klasse hat darüberhinaus eine Methode Report mit einer String-Ausgabe, mit der ich schnell ihre Daten ausgeben kann (hier eine Kommandozeilen-Interpretation, für den Desktop oder das Web müsste der Text z.B. in eine MsgBox ausgegeben werden):

Return Art + " macht "+Laut

Ein Print Tier1.Report bringt dann auch die Ausgabe

Hund macht Wuff

Wenn ich jetzt eine neue Instanz der Klasse Tier erstelle und dieser das Objekt Tier1 zuweise, erhalte ich auch das erwartete Ergebnis:

Dim Tier2 as New Tier
Tier2 = Tier1
Print Tier2.Report

Hund macht Wuff

Bisher alles ganz wie erwartet. Wenn ich aber nun mein Tier2 umdefiniere:

Tier2.Art = "Katze"
Tier2.Laut ="Miau"

und dann aber Tier1(!!) reporten lasse, stelle ich fest, dass ich nicht nur Tier2 felinisiert habe, sondern Tier1 ebenso dran glaube musste:

Katze macht Miau

Warum ist das so? Der Operator = in der Zeile Tier2 = Tier1 weist nicht allen Eigenschaften von Tier2 den Wert von Tier1 zu, sondern lässt Tier2 identisch mit Tier1 sein! Ich habe zwar zwei separate Instanzen, beide zeigen jedoch auf die gleiche Stelle im Arbeitsspeicher.

Will man wirklich eine eigenständige Kopie von Tier1 erstellen, findet programmierer sich häufig mit endlosen Methoden beschäftigt, die Eigenschaft für Eigenschaft kopieren. Also wie eine

Method Klon (Original As Tier, Kopie As Tier)
Kopie.Art = Original.Art
Kopie.Laut = Original.Laut

 

Bei zwei Properties ist der Aufwand ja noch ganz erträglich, aber die Klasse ist ja noch lange nicht ausgereizt. Bei jeder Ergänzung der Klasse (Anzahl der Beine, Schwanz ja/nein …) muss man nun wieder Hand an die Methode legen und die neuen Eigenschaften nachrüsten. Und wenn man mehr als eine neue Klasse in seinem Projekt hat … Na, Sie können sich den Aufwand vorstellen. Oder haben ihn häufiger schon selbst erlebt.

Viel praktischer wäre doch eine Klon-Methode für alle Objektarten. Und das geht sehr komfortabel, nämlich mit Introspection.
Introspection ermöglicht es Objekten, sich während der Laufzeit selbst zu betrachten. Sehr gründlich sogar, nämlich in Form detaillierter Listen (vielmehr Arrays) – z.B. für alle Properties. Was zufällig genau die Methode ist, die wir gerade brauchen.
Am besten geeignet ist für so eine Geschichte ein Modul, um sie als globale Ergänzung zur Verfügung zu stellen. Und darin eine

Method Klon (Original As Object, Kopie As Object)
dim Intro as Introspection.TypeInfo = Introspection.GetType (Original)
For Each Eigenschaft as Introspection.PropertyInfo in Intro.getproperties
if Eigenschaft.IsPublic and Eigenschaft.CanRead _
and Eigenschaft.CanWrite then
Eigenschaft.Value (Kopie) = Eigenschaft.Value (Original)
end if
Next

Wenn ich nun nach der Erstellung von Tier2 die Zeile

Klon (Tier1,Tier2)

ergänze, habe ich mir nicht nur diesmal, sondern für alle Zukunft eine Menge Arbeit gespart – einfach das Modul in ein neues Projekt kopieren, in dem es benötigt wird.
Das alles ist im übrigen nicht auf meinem Mist gewachsen, sondern Bestandteil des sehr sehenswerten Webinars http://www.youtube.com/watch?v=v5leKed6CSc
Und nur ein kleiner Teil davon – Jeremy Cowgar erläutert eine Menge weiterer, sehr hilfreicher Introspection-Möglichkeiten.

Obiges kleines Beispielprogramm finden Sie hier:  Instropection Modul.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s