Galileo Computing <openbook>
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


C# von Eric Gunnerson
Die neue Sprache für Microsofts .NET-Plattform
C# - Zum Katalog
gp Kapitel 12 Versionssteuerung mit new und override
  gp 12.1 Ein Beispiel zur Versionssteuerung

Kapitel 12 Versionssteuerung mit new und override

Softwareprojekte liegen selten in nur einer Codeversion vor, die nie überarbeitet wird, es sei denn, die Software erblickt nie das Licht der Welt. In den meisten Fällen möchte der Softwareprogrammierer Änderungen vornehmen können, und der Client muss sich an diese Änderungen anpassen.

Die Handhabung solcher Probleme wird als Versionssteuerung bezeichnet und gehört zu den schwierigeren Aufgaben bei der Softwareentwicklung. Ein Grund hierfür ist der, dass Planung und vorausschauendes Denken gefragt sind. Mögliche Bereiche für Änderungen müssen ermittelt werden und das Design muss Änderungen ermöglichen.

Ein weiterer Punkt, der die Versionssteuerung schwierig macht, besteht darin, dass die meisten Ausführungsumgebungen dem Programmierer hierbei nicht viel Unterstützung bieten. In C++ verfügt der kompilierte Code über interne Informationen zu Größe und Layout aller enthaltenen Klassen. Wenn Änderungen umsichtig vorgenommen werden, können die Klassen überarbeitet werden, ohne dass alle Benutzer eine Neukompilierung durchführen müssen; die auferlegten Beschränkungen sind jedoch gravierend. Wenn eine Kompatibilität nicht länger gewährleistet ist, müssen alle Benutzer zur Verwendung der neuen Version eine Neukompilierung vornehmen. Dies muss nicht unbedingt schlimm sein, obwohl das Installieren einer neuen Bibliotheksversion dazu führen kann, dass Anwendungen nicht mehr funktionieren, die ältere Versionen der Bibliothek verwenden.

Verwaltete Umgebungen, die keine Klassenmitglieder oder Layoutinformationen in den Metadaten offen legen, eignen sich besser für die Versionssteuerung, dennoch ist es möglich, Code zu schreiben, dessen Versionen nur schwer gesteuert werden können.


Galileo Computing

12.1 Ein Beispiel zur Versionssteuerung  toptop

Im folgenden Code wird ein einfaches Beispiel für die Versionssteuerung dargestellt. Das Programm verwendet eine Klasse namens Control, die durch eine andere Firma bereitgestellt wird.

public class Control
{
}
public class MyControl: Control
{
}

Während der Implementierung von MyControl wird die virtuelle Funktion Foo() hinzugefügt:

public class Control
{

}
public class MyControl: Control
{
    public virtual void Foo() {}
}

Dies funktioniert gut, bis ein Aktualisierungshinweis vom Lieferanten des Control-Objekts eintrifft. Die neue Bibliothek umfasst eine virtuelle Funktion namens Foo() für das Control-Objekt.

public class Control
{
        // neu hinzugefügte virtuelle Funktion
    public virtual void Foo() {}
}
public class MyControl: Control
{
    public virtual void Foo() {}
}

Die Tatsache, dass Control als Funktionsname Foo() verwendet, ist lediglich Zufall. In der C++-Umgebung nimmt der Compiler in diesem Fall an, dass die Foo()-Version in MyControl den Effekt hat, den ein virtual override von Foo() in Control haben sollte und ruft blindlings die Version in MyControl auf.

Das ist schlecht.

In der Java-Umgebung geschieht dies auch, hier liegt der Fall unter Umständen jedoch noch schlimmer: Wenn die virtuelle Funktion nicht über die gleichen Parameter und Mitgliedstypen verfügt, betrachtet der Klassenlader das Foo() in MyControl als unzulässige Außerkraftsetzung von Foo() in Control, was dazu führt, dass die Klasse zur Laufzeit nicht geladen werden kann.

In C# und der .NET-Laufzeitumgebung wird eine mit virtual definierte Funktion immer als Stamm für ein virtuelles Dispatching betrachtet. Wird eine Funktion in einer Basisklasse eingeführt, die als virtuelle Basisfunktion einer vorhandenen Funktion betrachtet werden könnte, bleibt das Laufzeitverhalten unverändert.

Wenn die Klasse anschließend kompiliert wird, erzeugt der Compiler jedoch eine Warnung, in der der Programmierer aufgefordert wird, den beabsichtigten Versionszweck anzugeben. In unserem Beispiel wird der Modifikator new vor der Funktion eingefügt, um als Standardverhalten festzulegen, dass die Funktion nicht außer Kraft gesetzt wird.

class Control
{
    public virtual void Foo() {}
}
class MyControl: Control
{
        // keine Außerkraftsetzung
    public new virtual void Foo() {}
}

Das Vorhandensein von new unterdrückt die Warnung.

Wenn andererseits die abgeleitete Version eine Außerkraftsetzung der Funktion in der Basisklasse sein soll, wird der Modifikator override verwendet.

class Control
{
    public virtual void Foo() {}
}
class MyControl: Control
{
        // Außerkraftsetzung von Control.Foo()
public override void Foo() {} }

So wird dem Compiler mitgeteilt, dass die Funktion tatsächlich außer Kraft gesetzt wird.


   

Select * from SQL Server 2000




Copyright © Galileo Press GmbH 2001 - 2002
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de