Kann Java abstrakte Typ-Member simulieren?


Scala kennt von Anfang an abstrakte Typ-Member als Alternative zu Generics. Eine Übersicht findet sich hier, und ich habe auch schon damit herumgespielt. Die Kurzfassung: Während generische Klassen ihre Parameter nach außen bekanntmachen, und diese überall mit „durchgeschleift“ werden (müssen), werden abstrakte Typ-Member eher als eine Art Implementierungsdetail angesehen und somit sozusagen als „innere Angelegenheit“ behandelt.

Und gestern abend dämmerte mir, das Java zumindest prinzipiell etwas Ähnliches erlaubt – und nicht erst seit Java 8. Ich habe keine Ahnung, wie weit diese „Technik“ trägt – und ganz sicher ist sie nicht so flexibel wie Scalas Ansatz, der ja „dafür gebaut“ worden ist. Aber ich werde gleich zwei Instanzen mit unterschiedlichen Member-Typen in ein und dieselbe Liste packen – ohne Wildcards, Raw-Types, Casts oder Compiler-Warnungen. Sozusagen „innen generisch, außen nicht“ – ähnlich wie bei abstrakten Typ-Membern:

public class Outer<T> {

    public class Inner {
        public final T t;

        public Inner(T t) {
            this.t = t;
        }
    }

    public static void main(String[] args) {
        List<Outer.Inner> list = new ArrayList<>();
        list.add(new Outer<String>().new Inner("blubb"));
        list.add(new Outer<Integer>().new Inner(42));
        for(Outer.Inner inner : list) {
            System.out.println(inner.t);
        }
    }
}

Tadaaaaa! Das ist also der Trick: Innere Klassen, die die Generics von ihren äußeren Klassen „benutzen“. Übrigens: Wer solche seltsamen Konstruktoraufrufe wie im Beispielcode noch nicht gesehen hat, ist nicht allein – ich kannte die Syntax auch nicht, bis ich für die „Java Programmer“-Zertifizierung von Oracle lernen musste (daher auch die „Inspiration“ für diesen etwas kranken Code). Ich muss erst einmal sehen, in wie weit dieses Konstrukt überhaupt sinnvoll ist, und wie groß die Beschränkung durch die erzwungene „Innerklassigkeit“ in der Praxis ist. Falls ihr auch damit herumspielt, würden mich natürlich die Ergebnisse eurer Experimente brennend interessieren.

[Update]
Ich bin darauf hingeweisen worden, dass der „volle“ Typ meiner Liste eigentlich etwas wie List<Outer<String>.Inner> sein müsste, ich hier also doch mit Raw-Types arbeite (auch wenn ich keine Warnung sehe). Das macht das Ganze natürlich hinsichtlich der Typsicherheit obsolet, weil damit kein Unterschied zu einer normalen generischen Top-Level-Klasse, die als Raw-Typ verwendet wird, besteht. Schade…

Advertisements

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