<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://mletkin.net/index.php?action=history&amp;feed=atom&amp;title=Generics_und_Klassen_mit_vielen_Gesichtern</id>
	<title>Generics und Klassen mit vielen Gesichtern - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://mletkin.net/index.php?action=history&amp;feed=atom&amp;title=Generics_und_Klassen_mit_vielen_Gesichtern"/>
	<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Generics_und_Klassen_mit_vielen_Gesichtern&amp;action=history"/>
	<updated>2026-05-06T17:21:09Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in MimiPedia</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>https://mletkin.net/index.php?title=Generics_und_Klassen_mit_vielen_Gesichtern&amp;diff=89&amp;oldid=prev</id>
		<title>Ullrich: Die Seite wurde neu angelegt: „Category:Java Java kennt keine Mehrfachvererbung, eine Klasse kann immer nur von &#039;&#039;einer&#039;&#039; Klasse abgeleitet werden. Das alternative Konzept sind Interface…“</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Generics_und_Klassen_mit_vielen_Gesichtern&amp;diff=89&amp;oldid=prev"/>
		<updated>2021-10-05T16:34:07Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „&lt;a href=&quot;/index.php?title=Kategorie:Java&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Kategorie:Java (Seite nicht vorhanden)&quot;&gt;Category:Java&lt;/a&gt; Java kennt keine Mehrfachvererbung, eine Klasse kann immer nur von &amp;#039;&amp;#039;einer&amp;#039;&amp;#039; Klasse abgeleitet werden. Das alternative Konzept sind Interface…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Category:Java]]&lt;br /&gt;
Java kennt keine Mehrfachvererbung, eine Klasse kann immer nur von &amp;#039;&amp;#039;einer&amp;#039;&amp;#039; Klasse abgeleitet werden.&lt;br /&gt;
Das alternative Konzept sind Interfaces: Jede Klasse kann – zusätzlich zu ihrer Superklasse – beliebig&lt;br /&gt;
viele Interfaces implementieren. Auf diese Weise kann ein Objekt einer Klasse – je nach Kontext – unterschiedliche&lt;br /&gt;
Schnittstellen haben und unterschiedlich behandelt werden. Wie aber stellt man es an, ein Objekt gleichzeitig&lt;br /&gt;
unter mehreren Blickwinkeln zu betrachten? Zur Motivation und zur Erklärung dieser zunächst etwas akademisch&lt;br /&gt;
anmutenden Frage diene uns ein einfaches Beispiel. Angenommen, wir haben zunächst ein Interface das das Volumen&lt;br /&gt;
von beliebigen Behältern beschreibt:&lt;br /&gt;
{{java|code=&lt;br /&gt;
interface Behaelter {&lt;br /&gt;
    double volumen();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Dazu haben wir ein Interface, über das wir Informationen zum Inhalt abfragen können – zum Beispiel das spezifische Gewicht:&lt;br /&gt;
{{java|code=&lt;br /&gt;
interface Inhalt {&lt;br /&gt;
    double dichte();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Mit diesen beiden Interfaces können wir nun – zum Beispiel um ein Schiff zu beladen – verschiedene Behälter&lt;br /&gt;
definieren, die unterschiedliche Dinge enthalten können; über die fehlenden Maßeinheiten sehen wir mal großzügig&lt;br /&gt;
hinweg. Von der weiteren Natur dieser Behälter sind unsere Interfaces völlig unabhängig:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public class Zuckersack implements Behaelter, Inhalt {&lt;br /&gt;
    @Override&lt;br /&gt;
    public double volumen() {&lt;br /&gt;
        return 100;&lt;br /&gt;
    }&lt;br /&gt;
    @Override&lt;br /&gt;
    public double dichte() {&lt;br /&gt;
        return 1.6;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Die Aufgabe besteht nun darin, eine Rechner-Klasse zu bauen die das Gewicht gefüllter Gefäße berechnet. Eine&lt;br /&gt;
ebenso billige wie häßliche Methode sähe etwa so aus:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public double gewicht(Object dings) {&lt;br /&gt;
    if (dings instanceof Behaelter &amp;amp;&amp;amp; dings instanceof Inhalt) {&lt;br /&gt;
        return ((Behaelter) dings).volumen() * ((Inhalt) dings).dichte();&lt;br /&gt;
    }&lt;br /&gt;
    throw new IllegalArgumentException();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Abgesehen von der mangelnden Übersichtlichkeit fliegt uns das Konstrukt erst bei falscher Anwendung zur&lt;br /&gt;
Laufzeit um die Ohren. Besser wäre es, wenn wir schon zur Compile-Zeit erführen, ob ein Objekt als Methoden-&lt;br /&gt;
Argument geeignet ist oder nicht. Dank Javas statischer Typisierung sollte das eigentlich kein Problem sein und&lt;br /&gt;
seit Java 1.5 kann man das mit Generics auch sehr viel hübscher hinbekommen.&lt;br /&gt;
Eine generische Methoden-Signatur kann in Java zum Beispiel so aussehen:&lt;br /&gt;
{{java|code=public &amp;lt;T&amp;gt; double foo(T dings);}}&lt;br /&gt;
Was die Methode tut, sei erstmal egal, wir sehen uns zunächst nur die Signatur an:&lt;br /&gt;
&lt;br /&gt;
{{java|foo}} sei eine Methode, die einen Parameter des generischen Typs {{java|T}} übernimmt und als Ergebnis einen&lt;br /&gt;
double-Wert liefert. Der parametrisierte Typ {{java|T}} wird dazu in spitzen Klammern vor dem Rückgabe-Wert angegeben.&lt;br /&gt;
Er kann dann als Typ in der Parameterliste und als Rückgabe-Typ verwendet werden. Im obigen Beispiel brauchen wir ihn&lt;br /&gt;
nur für den Parameter {{java|dings}}. Da im Beispiel keine Einschränkungen gemacht werden, kann {{java|T}} beim Aufruf&lt;br /&gt;
der Methode durch beliebige Klasse oder ein beliebiges Interface ersetzt werden. Der Aufruf&lt;br /&gt;
{{java|code=foo(Integer.valueOf(1));}}&lt;br /&gt;
ist ebenso zulässig wie der Aufruf&lt;br /&gt;
{{java|code=foo(&amp;quot;1&amp;quot;);}}&lt;br /&gt;
Um mit dem Parameter etwas Sinnvolles anstellen zu können, müssen wir ihn etwas einschränken. Zunächst sollen&lt;br /&gt;
nur Klassen erlaubt werden, die das Interface {{java|Behaelter}} implementieren:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public &amp;lt;T extends Behaelter&amp;gt; double wasDrinIst(T dings) {&lt;br /&gt;
    return dings.volumen();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Der Parameter {{java|dings}} muß damit ein Objekt einer Klasse sein, die das Interface {{java|Behaelter}} implementiert und&lt;br /&gt;
daher können wir darauf die Methode {{java|volumen()}} aufrufen. Tatsächlich ist die generische Methoden-Deklaration&lt;br /&gt;
äquivalent zu dieser klassischen Variante:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public double wasDrinIst(Behaelter dings) {&lt;br /&gt;
    return dings.volumen();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Und jetzt kommt der Trick: In der klassischen Variante &amp;#039;&amp;#039;ohne&amp;#039;&amp;#039; Generics kann der Parameter {{java|dings}} nur einen einzigen&lt;br /&gt;
Typ haben, im Beispiel ist das das Interface {{java|Behaelter}}. Im Gegensatz dazu kann der generische Typ {{java|T}} mehrere&lt;br /&gt;
Typen haben, die durch den {{java|&amp;amp;}}-Operator verknüpft werden. Die endgültige Methode zur Berechnung des Gewichts&lt;br /&gt;
sieht dann so aus:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public &amp;lt;T extends Behaelter &amp;amp; Inhalt&amp;gt; double gewicht(T dings) {&lt;br /&gt;
    return dings.volumen() * dings.dichte();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
{{java|T}} ist nun ein Typ, der die Interfaces {{java|Behaelter}} &amp;#039;&amp;#039;und&amp;#039;&amp;#039; {{java|Inhalt}} implementiert.&lt;br /&gt;
Damit können wir die Methode {{java|volumen()}} aus dem Interface {{java|Behaelter}} und die Methode&lt;br /&gt;
{{java|dichte()}} aus dem Interface {{java|Inhalt}} auf das Objekt {{java|dings}} anwenden. Tatsächlich&lt;br /&gt;
kann man beliebig viele Typen angeben, die mit den {{java|&amp;amp;}}-Operator verknüpft werden. Darunter darf&lt;br /&gt;
auch &amp;#039;&amp;#039;eine&amp;#039;&amp;#039; Klasse sein, diese muß dann aber an erster Stelle stehen. Korrekt – wenn auch redundant – wäre&lt;br /&gt;
folgende Definition:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public &amp;lt;T extends Object &amp;amp; Behaelter &amp;amp; Inhalt&amp;gt; double gewicht(T dings) {&lt;br /&gt;
    return dings.volumen() * dings.dichte();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Die Anwendung der Interface-Kombination ist nicht auf Methoden beschränkt. Man kann sie auch zur&lt;br /&gt;
parametrisierten Definition generischer Klassen verwenden:&lt;br /&gt;
{{java|code=&lt;br /&gt;
public class Ladung &amp;lt;T extends Behaelter &amp;amp; Inhalt&amp;gt; {&lt;br /&gt;
    List&amp;lt;T&amp;gt; fracht = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Den Code zu den aufgeführten Beispielen giebt&amp;#039;s auf [https://github.com/mletkin/JavaSamples/tree/master/src/main/java/org/ully/samples/generics/inheritance Git-Hub].&lt;/div&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
</feed>