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
|
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
|
anbietet. Das ist das C-Äquivalent zu einem unbeschränkten generischen ADT.
Ein generischer Stack in Eiffel
|
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: