Generische Programmierung

Generische Programmierung

Generische Programmierung ist ein Verfahren zur Entwicklung wiederverwendbarer Software-Bibliotheken. Dabei werden Funktionen möglichst allgemein entworfen, um für unterschiedliche Datentypen und Datenstrukturen verwendet werden zu können.

Die Implementierung erfolgt bei einigen Programmiersprachen durch das Konzept generischer Typen bzw. Templates – so gestalten sich dynamische Programmiersprachen, bei denen sich der Typ einer Variable zur Laufzeit ändern darf, durch ihre verallgemeinerte Polymorphie generisch. Von Sprachen, die solche Mechanismen bieten, sagt man auch, dass sie Generik erlauben.

Wesentlich bei der generischen Programmierung ist, dass die Algorithmen nicht für einen bestimmten Datentyp geschrieben werden, sondern nur bestimmte Anforderungen an die Typen stellen. Das Prinzip wird auch parametrische Polymorphie genannt.

Paradebeispiel ist die C++-Standardbibliothek der Programmiersprache C++, bei der die Algorithmen so weit wie möglich von den Datenstrukturen, mit denen sie arbeiten, getrennt werden.

Inhaltsverzeichnis

Vergleich verschiedener Techniken

Ein Beispiel liefert die Maximumsfunktion

\max: T \times T \to T,

die für zwei gegebene Werte a, b desselben Typs den größeren Wert max(a,b) zurückgibt.

Voraussetzung ist, dass a und b miteinander vergleichbar sind, der Ausdruck a \le b also definiert ist und eine Ordnung beschreibt.

Neuschreiben der Algorithmen für jeden Datentyp

In klassischen Programmiersprachen wie C könnte man hier für jeden Datentyp eine Funktion programmieren, die jeweils das gleiche Ergebnis im entsprechenden Typ erzeugt.

Die folgenden Funktionen ermitteln von den beiden Zahlen a und b jeweils die Größere, allerdings einmal als Integer und einmal als Float:

int maxInt(int a, int b)
{
  if (a < b)
    return b;
  else
    return a;
}
float maxFloat(float a, float b)
{
  if (a < b)
    return b;
  else
    return a;
}

Hierbei fällt auf, dass der Code an sich immer derselbe ist, nur die Typen unterscheiden sich.

Generische Programmierung

Hier wird der Typ durch den Präprozessor bestimmt.

#define Item int

Der Zieldatentyp in einer separaten Datei.

static Item maximum;

In derselben Datei befindet sich auch der Speichermechanismus.

static void
save (void *tmp)
{
  maximum = *((Item*)tmp);
}

Natürlich gibt es hier eine spezielle Vergleichsmethode für den Typ.

int
compare (void * aa, void * bb)
{
  if ( *((Item*)aa) < *((Item*)bb) )
    return -1;
 
  return 0;
}

Der generische Algorithmus zur Wiedergabe des Maximums.

void
max (void *aa, void *bb, void save (void *) )
{
  if ( compare (aa, bb) )
    save (bb);
  else
    save (aa);
}

Die Funktion max ist hiermit komplett generisch. Man bemerkt, dass die Funktionen save und compare einen konkreten Datentyp verwenden, diese werden aber später, da sie nicht zur Grammatik des Algorithmus gehören, gekapselt.

Verwendung objektorientierter Mittel

Der objektorientierte Ansatz funktioniert im Kontext statischer Typisierung nicht zufriedenstellend. Zwar lässt sich hier mit Interfaces oder Mehrfachableitung Klassen um "andere" Datentypen erweitern, sodass sich mittels Polymorphie das Verhalten der generischen Programmierung zum Teil nachbauen lässt, allerdings wird die vollständige Unabhängigkeit von unterschiedlichen Typen (bzw. Klassen) damit nicht umgesetzt, weil es sich bei diesen Techniken auch nicht strenggenommen um objektorientierte Techniken handelt.

Definiert man (beispielsweise in C++) eine Klasse Vergleichbares und leitet davon zum Beispiel für eine physikalische Simulation die Klassen Laenge und Masse ab (sagt also, dass sowohl Längen als auch die Masse etwas vergleichbares sind), so kann man zwar schreiben:

 Vergleichbares& max(Vergleichbares& a, Vergleichbares& b)
 {
   if (a < b)
     return b;
   else
     return a;
 }

aber es gibt immer noch zwei Probleme:

  • Zunächst, dass der Ergebnistyp nur „Vergleichbares“ ist; man muss dem Compiler also beim Aufruf explizit sagen, dass das Maximum zweier Längen wieder eine Länge ist (sofern man dessen Längeneigenschaften benutzen will, was wahrscheinlich ist), vor allem aber,
  • dass diese Funktion es erlaubt, das Maximum einer Länge und einer Masse zu „bestimmen“, obwohl diese Operation keinen physikalischen Sinn hat.

Templates

Generische Programmierung, beispielsweise in C++ über Templates realisiert, verbindet nun die Flexibilität des Makros mit der Typsicherheit und den anderen Eigenschaften der Funktion. Die generische Implementierung von max in C++ ist

 template<typename T>
 T max(T a, T b)
 {
   if (a < b)
     return b;
   else
     return a;
 }

Die so definierte Funktion max() kann nun für alle Typen mit Vergleichsoperator verwendet werden.

Ein weiterer Vorteil ist, dass man nicht explizit bei der Definition sagen muss, dass ein Typ vergleichbar ist (zum Beispiel durch Ableiten von einer entsprechenden Klasse), sondern man muss nur sicherstellen, dass er die nötigen Eigenschaften hat (in diesem Fall einen operator < mit korrekter Semantik). Auf diese Weise können auch Typen mit der Funktion verwendet werden, die in Unkenntnis der Funktion entworfen wurden (beispielsweise die eingebauten Typen der Programmiersprache).

Ein Algorithmus sollte dabei stets möglichst wenig vom Typ fordern. So arbeiten die Algorithmen der STL nicht direkt auf den Containern, sondern mit Iteratoren. Auf diese Weise werden sie weitgehend unabhängig von den genauen Eigenschaften des speziellen Containers und können teilweise sogar direkt auf Ein- und Ausgabeströmen arbeiten.

Generische Programmierung in verschiedenen Programmiersprachen

  • Wie bereits erwähnt, wird die generische Programmierung in C++ durch Templates unterstützt.
  • In Ada gab es generische Typen schon lange vor der Einführung von Templates in C++.
  • In ABAP gibt es ebenfalls generische Datentypen.
  • In Java kommen generische Typen seit der Version 1.5 vor.
  • In den .NET-Sprachen C# und VB .NET (ab .NET 2.0) gibt es die generischen Typen (generics).
  • In der Programmiersprache Eiffel existieren generische Klassen.
  • Die funktionale Programmiersprache ML (und Abkömmlinge wie OCaml) sowie Haskell erlauben generische Programmierung. Typ-Polymorphie ist dort konzeptuelle Grundlage. Es lassen sich sogar Module generieren. Generische Module („parametric modules“) werden hier als Funktor bezeichnet. Man kann Funktoren Module als Parameter übergeben und erhält ein neues Modul als Ergebnis.
  • In Programmiersprachen wie Python, welche Datentypen dynamisch verwalten und außerdem Operatoren unterstützen, kann praktisch jede Methode im Sinne der generischen Programmierung verwendet werden.
  • Schließlich kann man auch die Makros in C zur generischen Programmierung benutzen, wenngleich sie ursprünglich nicht zu diesem Zweck eingeführt wurden.

Softwaretechnik

Ein generisches Modell ist an spezifische Gegebenheiten einer konkreten Situation anpassbar; z. B. ein generisches Vorgehensmodell wie Wasserfall- oder Spiralmodell an ein konkretes Projekt. Dieser Vorgang wird im Bereich des Software-Engineering auch Tailoring genannt.

Ändert sich das generische Modell, kann man dessen Ausprägungen leicht anpassen, wenn der Weg vom Modell zur Ausprägung detailliert beschrieben ist und man nur die geänderten Elemente verfolgen muss. Bei nicht-generischen Modellen spricht man in diesem Zusammenhang auch von Überanpassung.

Siehe auch


Wikimedia Foundation.

Игры ⚽ Нужно сделать НИР?

Schlagen Sie auch in anderen Wörterbüchern nach:

  • Generische Programmierung in Java 5.0 — Generische Programmierung wird in Java durch so genannte Generics ermöglicht. Der Begriff steht synonym für „parametrisierte Typen“. Die Idee dahinter ist zusätzliche Variablen für Typen, sog. Typ Variablen, einzuführen. Diese repräsentieren zum… …   Deutsch Wikipedia

  • Generische Programmierung in Java — wird durch sog. Generics ermöglicht. Der Begriff steht synonym für „parametrisierte Typen“. Die Idee dahinter ist, zusätzliche Variablen für Typen einzuführen. Diese Typ Variablen repräsentieren zum Zeitpunkt der Implementierung unbekannte Typen …   Deutsch Wikipedia

  • Vererbung (objektorientierte Programmierung) — Vererbung dargestellt mittels UML. Die abgeleitete Klasse hat die Attribute x und y und verfügt über die Methoden a und b (im UML Sprachgebrauch Operationen a und b). Die Vererbung (engl. Inheritance) ist eines der grundlegenden Konzepte der… …   Deutsch Wikipedia

  • Generative Programmierung — Die Generative Programmierung ist ein besonderes Programmierparadigma bei der methodischen Softwareentwicklung. Charakteristisch für die generative Programmierung ist die automatische Erzeugung von Programmcode durch einen Generator.… …   Deutsch Wikipedia

  • Vererbung (Programmierung) — Vererbung dargestellt mittels UML. Die abgeleitete Klasse hat die Attribute x und y und verfügt über die Methoden a und b (im UML Sprachgebrauch Operationen a und b). Die Vererbung (engl. Inheritance) ist eines der grundlegenden Konzepte der… …   Deutsch Wikipedia

  • Bibliothek (Programmierung) — Eine Programmbibliothek bezeichnet in der Programmierung eine Sammlung von Programmfunktionen für zusammengehörende Aufgaben. Bibliotheken sind im Unterschied zu Programmen keine eigenständig lauffähigen Einheiten, sondern Hilfsmodule, die… …   Deutsch Wikipedia

  • Template (Programmierung) — Templates (engl. für Schablonen), auch Mustervorlagen oder Schablone, sind fortgeschrittene Elemente von Programmiersprachen. Sie sind „Programmgerüste“, die bei Bedarf vom Übersetzer instanziiert und als normale Klassen oder Funktionen zur… …   Deutsch Wikipedia

  • Polymorphie (Programmierung) — Polymorphie (griechisch, „Vielgestaltigkeit“) ist ein Konzept in Programmiersprachen, das die Fähigkeit eines Bezeichners beschreibt, abhängig von seiner Verwendung unterschiedliche Datentypen anzunehmen. Das Gegenteil der Polymorphie ist die… …   Deutsch Wikipedia

  • Aspektorientierte Programmierung — (AOP) ist ein Programmierparadigma für die Objektorientierte Programmierung, um generische Funktionalitäten über mehrere Klassen hinweg zu verwenden (Cross Cutting Concern). Logische Aspekte eines Anwendungsprogramms werden dabei von der… …   Deutsch Wikipedia

  • Generisches Konzept — Generische Programmierung ist ein Verfahren zur Entwicklung wiederverwendbarer Software Bibliotheken. Dabei werden Funktionen möglichst allgemein entworfen, um für unterschiedliche Datentypen und Datenstrukturen verwendet werden zu können. Die… …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”