2016-05-31 24 views
2

Ich versuche, eine Hierarchie von Klassen zu erstellen, beginnend mit einer abstrakten Klasse mit einem generischen Typ. Und dann verwenden Sie einen erweiterten Typ des Generic in der 2. Generation von Kinderklassen. Da ich ziemlich sicher bin unklar, das ist, hier ein Beispiel:Java-Generics-Hierarchie

Die Idee wäre, eine Tabelle mit Elementen haben, also im Grunde:

Simple UML of what I'm trying to do

abstract class AbstractTableOfItems<T> -> Die allgemeine Art der Tabelle

class Foo -> Eine Art von Artikel

class Bar -> Eine andere Art zum Produkt

class SonOfFoo extends Foo

class TableOfFoo extends AbstractTableOfItems<Foo>

class TableOfBar extends AbstractTableOfItems<Bar>

So weit, so gut, alles ist in Ordnung (lassen Sie sich über den Inhalt der Klassen nicht kümmern, es ist nicht der Punkt hier).

Aber dann möchte ich eine Tabelle SonOfFoo und ich möchte es TableOfFoo erweitern, da SonOfFoo von Foo erbt. Dies scheint nicht möglich zu sein. Vielleicht denke ich in die falsche Richtung, aber ich verstehe einfach nicht warum.

class TableOfSonOfFoo extends TableOfFoo

compiliert ist aber falsch, weil es immer noch eine Tabelle von Foo, der generischen Typ verwendet Foo sein würde.

class TableOfSonOfFoo extends TableOfFoo<SonOfFoo>

nicht nicht kompiliert, da der generische Typ auf dem AbstractTableOfItems ist.

Also ok ich sagen, wollen wir versuchen, TableOfFoo neu zu definieren, so kann es akzeptieren Vererbung:

class TableOfFoo extends AbstractTableOfItems<? extends Foo>

wieder falsch: „Ein Supertyp darf keine Wildcard angeben“ (Ich bin nicht sicher, ob ich voll und ganz verstehen dieses).

Ich kann AbtractTableOfItems nicht berühren, da es nicht so allgemein sein würde, wie ich will. Also bin ich hier irgendwie festgefahren. Ich verstehe, es würde funktionieren, nur TableOfSonOfFoo erben direkt von AbstractTableOfItems, aber dann würde ich alle Implementierungen verlieren von TableOfFoo.

Ich könnte dies umgehen, aber ich versuche, an eine Hierarchie zu denken und zu verstehen, warum das nicht funktioniert.

Antwort

4

Dies kompiliert:

class TableOfFoo<F extends Foo> extends AbstractTableOfItems<F> 

Das heißt: Ich habe nicht die oben Design mögen. Wenn Sie die konkreten Typen TableOfFoo und TableOfBar angeben, führen diese Klassen wahrscheinlich mehr aus, als sie sollten. Vielleicht möchten Sie Ihr Design überprüfen und sehen, ob Sie Dinge vereinfachen könnten, indem Sie Aggregation statt Vererbung verwenden.

+0

Ich weiß, aber ich gab eine Alternative zu diesem Teil seiner Frage 'class TableOfFoo erweitert AbstractTableOfItems '. Ich denke nicht, dass die ganze Frage leicht zu beantworten ist. –

+0

Danke, das scheint zu funktionieren. Der Nachteil ist, dass ich jedes Mal, wenn ich den Typ "F" und die Klasse TableOfFoo verwende, explizit auf Foo umstellen muss, während es vorher implizit war. Aber es funktioniert tatsächlich so. "Vielleicht möchten Sie Ihr Design überprüfen und sehen, ob Sie Dinge vereinfachen könnten, indem Sie Aggregation statt Vererbung verwenden." Vielleicht bin ich mir in der Tat nicht so sicher über die Relevanz dieses Designs. – Zazou

+0

@ Zazou das klingt nicht richtig. Sie sollten kein Casting benötigen, wenn Sie Generika korrekt verwenden. Vielleicht sollten Sie eine Folgefrage für diese –

0

Ich hätte das lieber in Kommentare geschrieben, aber noch nicht genug Reputation. Haben Sie versucht:

class TableOfSonOfFoo extends AbstractTableOfItems<SonOfFoo> 

Dies scheint mir legitim und wäre meine erste Schätzung gewesen.

+0

1) Bitte schreiben Sie keine Fragen als Antwort. Wenn Sie nicht genug Reputation für Kommentare haben, beantworten Sie Fragen, bis Sie haben. 2) OP erklärte explizit, dass er 'AbstractTableOfItems' nicht direkt erweitern möchte. – Seelenvirtuose

1

Sie können Ihren TableOfFoo generischen, z.

class TableOfItems<T> extends AbstractTableOfItems<T> 

und ziehen Sie alle Funktionen, die Sie in diesem teilen möchten. Dann erstellen Sie Subklassen dieser:

class TableOfFoo extends TableOfItems<Foo> 
class TableOfSonOfFoo extends TableOfItems<SonOfFoo> 

Beachten Sie, dass AbstractTableOfItems<Foo> kein übergeordneter Typ von AbstractTableOfItems<SonOfFoo> ist, so TableOfFoo und TableOfSonOfFoo sind tatsächlich Geschwister in der Hierarchie.

+0

Danke für die Antwort, aber dadurch wäre TableOfItems eine Tabelle mit generischen Items "T" und keine Tabelle von Foo, was bedeutet, dass ich Foo nicht als meinen generischen Typ in den Methoden dieser Klasse verwenden kann. Welches war genau der Punkt dieser Hierarchie. – Zazou

+0

@Zazou so fügen Sie eine Bindung an die Typvariable: 'T erweitert Foo'. –

+0

Aber dann wäre es ein TableOfFoo, und TableOfItems wäre nicht nötig, und das wäre die Antwort von Sean Patrick Floyd, direkt darüber;) – Zazou