Ist Object Generische Programmierung
 
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Von GenerischeProgrammierung
Eine Alternative zur Parametrisierung von Klassen durch Typen ist die Ableitung aller Typen von einem Basistyp. Alles, was für diesen Basistyp (z.B. Object in Java [SpracheJava] oder Smalltalk [SpracheSmalltalk] oder id in Objective-C [SpracheObjectiveCee]) definiert ist auf alle Typen anwendbar. Der Unterschied zu generischer Programmierung ist aber, dass auf diese Weise Typ-Sicherheit verloren geht. Es ist ein entscheidender Unterschied, ob eine Behälterklasse Objekte von irgendeinem bestimmten Typ enthalten kann, oder ob sie Objekte von einem Typ Objekt enthalten kann.

Wenn eine Behälterklasse mit Hilfe eines Typs an der Wurzel der Klassenhierarchie verwirklicht wird, wie das in Smalltalk, Java oder Objective-C üblich ist, dann ist es beim Arbeiten mit Objekten in einer solchen Behälterklasse erforderlich, zur Laufzeit zu prüfen, ob das entnommene Objekt auch den Typ hat, der bei seiner Weiterverarbeitung erwartet wird. Das kann wie in Smalltalk dadurch geschehen, dass dem Objekt eine Nachricht geschickt wird, und zur Laufzeit entschieden wird, ob es diese auch versteht, oder es führt zu Konstrukten wie

private ModelIcon hitIcon(java.util.ListIterator i)
{
   while (i.hasNext())
   {
      ModelIcon item = (ModelIcon) i.next();
      if(item.isInside(_creationPosition.width,
                       _creationPosition.height))
         return item;
   }
   return null;
}

in Java, die ebenfalls erst durch einen Laufzeitfehler Typkonflikte feststellen. Hier muss ohne Unterstützung durch den Compiler sichergestellt werden, dass der Iterator wirklich über eine Liste von Objekten iteriert, die vom passenden Typ oder einem davon abgeleiteten Typ sind. Eine mit dem passenden Typ parametrisierte Liste ist etwas anderes. Hier kann die Typprüfung zur Übersetzungszeit vorgenommen werden.

Ist es nicht so, dass Smalltalk nur die Parametrisierung über Typen, und auch dieses nur über Polymorphismus und eine Klasse an der Wurzel der Klassenhierarchie erlaubt? -- KurtWatzka

Ist es nicht so, dass in Java Klassen verwendet werden können, die nicht als Object verwendet werden, sondern die ein gemeinsames Interface implementieren? -- HelmutLeitner

Interessant wäre das, wenn man einen Vector<interface>() machen könnte, oder ein MeinSpeziellerVector?<type>(parameter). Das Beispiel ganz oben mit hitIcon ist ja (in meinen Augen) definitiv nicht generisch. Naja. Zumindestens nicht generischer als ModelIcon. Dazu bräuchte man aber Object nicht. Ganz im Gegenteil. Das bringt nur die bereits angesprochene Laufzeitunsicherheit.

Das ist ein eleganter Übergang zu beschränkten generischen Programmen (oder: Funktionen, Klassen, Modulen). Trotzdem geht die TypSicherheit verloren. In C ist es nicht besonders kompliziert, einen ADT [AbstrakterDatenTyp?] Stack zu schreiben, der eine Schnittstelle wie

typedef struct stackType STACK;

int Stack_count(STACK *self);  // Anzahl der Elemente im Stack
int Stack_empty(STACK *self);  // Hat der Stack keine Elemente
void *Stack_item(STACK *self); // Liefert das oberste Element
void Stack_remove(STACK *self);// Entfernt das oberste Element
void Stack_put(STACK *self, void *item, size_t size); 
/* Legt eine Kopie des Elements auf den Stack */

anbietet. Das ist das C-Äquivalent zu einem unbeschränkten generischen ADT.

Ein generischer Stack in Eiffel

class STACK[G] feature
   count : INTEGER 
     -- Anzahl der Elemente im Stack
   empty : BOOLEAN is
     -- Hat der Stack keine Elemente
     do ... end
   item : G is
     -- Liefert das oberste Element
     do ... end
   remove is
     -- Entfernt das oberste Element
     do ... end
   put (x: G) is
     -- Legt eine Kopie von x auf den Stack
     do ... end
end

ist aber immer ein Stack von Elementen eines bestimmten Typs. Ein "STACK[ANY]" kann trotzdem Elemente von jedem beliebigen Typ aufnehmen, wenn dies notwendig ist.

Die Beschränkung auf Elemente, die ein bestimmtes Interface einhalten ist für sortierte Behälter sicher sinnvoll. Die Lösung in C++, dass eine template-Klasse nur mit Typ-Parametern instatiiert werden kann, die alle von der Implementation verwendeten Operationen anbietet, ist vieleicht nicht die beste Idee. Solche Beschränkungen in die syntaktische Unterstützung für generische Klassen einzubauen, wie in "VECTOR[G -> NUMERIC]" in Eiffel ist vieleicht eine bessere Lösung. In Vektor kann davon ausgegangen werden, dass G alles kann, was NUMERIC kann, aber ein "VEKTOR[COMPLEX]" ist immer noch typsicher.

Java löst das Problem nach innen, d. h. in einen geordneten Behälter kann nur eingefügt werden, was Comparable implementiert, aber es löst nicht das Problem, dass der Typ der Elemente auf andere Weise bekannt sein muss als durch seine ausdrückliche Nennung. -- kw

In Lisp (CLOS) und abgeleiteten Sprachen (Smalltalk, Dylan, java, ...) ist der erste Absatz nicht unbedingt gültig. Nicht alle Objektsysteme "dispatchen" nur zur Laufzeit. Allegro Common Lisp, Xanalys Lispworks, cmucl's python compiler, ML oder OCAML generieren sowohl typ-spezifischen Objektcode, und auch laufzeit-abhängige (= dynamische) Methodenaufrufe. Die meisten besseren dynamischen Objektsysteme optimieren ihre Methodenaufrufe zur Laufzeit (java??) und erlauben optionale Typisierung, so daß folgende Vorteile zu tragen kommen:

--ReiniUrban


KategorieOop KategorieDiskussion
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 10. Mai 2001 12:46 (diff))
Suchbegriff: gesucht wird
im Titel
im Text