Generics Vererbung Wildcard Interface

ninonino

Mitglied
Ich verstehe nicht warum ich in folgendem Beispiel in der ClassCollectionString-KLasse in der addList Methode nicht <ClassChild> für <? extends Class<String>> einsetzen kann ?
Java:
	abstract class Class<T>{
		
	}
	class ClassChild extends Class<String>{
		
	}
	interface ClassCollection<T>{
		void addList(ArrayList<? extends Class<T>>list);
		
	}
das geht :
Java:
	class ClassCollectionString implements ClassCollection<String>{

		@Override
		public void addList(ArrayList<? extends Class<String>> list) {
			// TODO Auto-generated method stub
			
		}
	}
das nicht :
Java:
	class ClassCollectionString implements ClassCollection<String>{

		@Override
		public void addList(ArrayList<ClassChild> list) {//<-----------------FEHLER
			// TODO Auto-generated method stub
			
		}
	}
Eclipse : ClassCollectionString must implement the inherited abstract method ClassCollection<String>.addList(ArrayList<? extends Class<String>>)
 
Zuletzt bearbeitet:
Ich habe mal dein sehr abstraktes Beispiel ein bisschen blumiger gemacht

Java:
	abstract class Haus<T>
	{
		 
	}
	
	class StringHaus extends Haus<String>
	{
	 
	}
	
	interface Strasse<T>
	{
		void addList(ArrayList<? extends Haus<T>>list);
	 
	}
	
	class ClassCollectionString implements Strasse<String>
	{
		 
		@Override
		public void addList(ArrayList<StringHaus> list) //<-----------------FEHLER
		{
			// TODO Auto-generated method stub
		}
	}

ich kämpfe grade noch ein wenig mit der Erklärung, warum das ganze nicht funktioniert wie du das möchtest. hier der code mit dem deine methoden-signatur korrekt ist:

Java:
	class StringHaus extends Haus<String>
	{
	 
	}
	
	interface Strasse<T>
	{
		void addList(ArrayList<T>list);
	 
	}
	
	class ClassCollectionString implements Strasse<StringHaus>
	{
		 
		@Override
		public void addList(ArrayList<StringHaus> list)
		{
			// TODO Auto-generated method stub
		}
	}

Edit::

problem ist folgendes: du definierst über dein interface ClassCollection, dass man als parameter für addList etwas vom typ ArrayList<? extends Class<T>> übergeben muss

wenn ich also bei ClassCollectionString<String> addList aufrufe, dann würde ich erwarten, das er alles entgegennimmt was eine ArrayList ist, dessen generic vom typ Class<String> ist

das kann z.B. ArrayList<ClassChild> sein, aber z.B. auch ArrayList<MySuperDuperClass extends Class<Anything extends String>> sein

wenn du also in ClassCollectionString.addList den typ ArrayList<ClassChild> als parameter erwartest erfüllst du nicht die anforderungen an das interface, weil dein typ andere mögliche kompatible typen ausschließt die eigentlich valide wären.


Edit2:

das schöne ist, du solltest so auch schon folgendes machen können:

Java:
ClassCollectionString<String> list = new ClassCollectionString<String>();
 // komplexer typ, der aber deinem interface gerecht wird
ArrayList<ClassChild> advancedChilds = new ArrayList<ClassChild>();
 // komplexer typ, den wir aber in eine allgemeinere liste packen, die aber auch dem interface gerecht wird
ArrayList<Class<String>> hiddenTypeChilds = new ArrayList<ClassChild>();
list.addList(advancedChilds);
list.addList(hiddenTypeChilds);
(ist im browser geschrieben, habs grad mal nicht in der IDE ausprobiert, sollte aber gehen)
 
Zuletzt bearbeitet:
Hey , vielen Dank schonmal !
Da kommen ein paar Fehlermeldungen.
Code:
	ClassCollectionString<String> list = new ClassCollectionString<String>();
//	ClassCollectionString is not generic; it cannot be parameterized with arguments <String>//	
	// komplexer typ, der aber deinem interface gerecht wird
	ArrayList<ClassChild> advancedChilds = new ArrayList<ClassChild>();
	// komplexer typ, den wir aber in eine allgemeinere liste packen, die aber auch dem interface gerecht wird
	ArrayList<Class<String>> hiddenTypeChilds = new ArrayList<ClassChild>();
//	Type mismatch: cannot convert from ArrayList<ClassChild> to ArrayList<Class<String>>
	list.addList(advancedChilds);
	list.addList(hiddenTypeChilds);
Habe die Funktion von Interfaces wohl noch nicht verstanden.
Gibt es denn eine Möglichkeit eine Methode mit generischem Parameter vorzuschreiben und diesen Parameter dann bei der implementierenden Klasse konkret zuzuweisen ?
 
Zuletzt bearbeitet:
Habe die Funktion von Interfaces wohl noch nicht verstanden.

zum thema Interface

Ein Interface bietet die möglichkeit, anzugeben das ein object einer klasse gewisse eigenschaften hat. Die idee dahinter ist folgende: ich habe mehrere verschiedene klassen die alle eine eigenschaft teilen. nun schreibe ich eine klasse die genau diese und nur diese eigenschaft benötigt. damit ich jetzt nicht für jede meiner verschiedenen klassen eine extra methode schreiben muss, kann ich eine schreiben die etwas vom typ des interface entgegennimmt.

Beispiel:
Java:
interface HatBeine
{
   int getBeine();
}

class Stuhl implements HatBeine
{
    // interface method
    int getBeine()
    {
         return 4;
    }

    // ....
}

class Tisch implements HatBeine
{
    // interface method
    int getBeine()
    {
         return 2;
    }

    // .....
}

class MoebelBeineZaehler
{
    public static getSummeBeine(List<HatBeine> liste)
    {
         int summe = 0;
         for (HatBeine b : liste)
        {
             summe = summe + b.getBeine();
        }
        return summe;
    }
}

ArrayList<HatBeine> moebelmitbeinen = new ArrayList<HatBeine>;
moebelmitbeinen.add(new Stuhl());
moebelmitbeinen.add(new Stuhl());
moebelmitbeinen.add(new Tisch());
MoebelBeineZaehler.getSummeBeine(moebelmitbeinen); // return ist 10
Erleuterung: Sowohl Tische, als auch Stühle haben Beine, damit ich jetzt nicht für beide in der Klasse MoebelBeineZaehler eine eigene Methode schreiben muss, bekommen beide Klassen das interface "HatBeine" in der die Funktion getBeine() definiert ist, die von getSummeBeine(...) genutzt wird.

edit: und richtig cool daran ist, dass ich jetzt auch einfach eine neue Klasse "Mensch implements HatBeine" machen kann und schwupp kann MoebelBeineZaehler.getSummeBeine(...) auch die automatisch mitzählen


Gibt es denn eine Möglichkeit eine Methode mit generischem Parameter vorzuschreiben und diesen Parameter dann bei der implementierenden Klasse konkret zuzuweisen ?

da stellt sich die Frage, warum du dann überhaupt einen generischen Typ brauchst, wenn du sowieso konkret zuweisen willst? Da kannst du den generic genausogut einfach weglassen.
Generics dienen dazu, einer Klasse beizubringen, dass ihr der typ eigentlich egal sein kann

Bspw. ist einer Liste eigentlich egal, ob da String, Object, Integer oder sonstwas drin sind denn das hat keinen Einfluss darauf, wie eine Liste funktioniert.
 
Zuletzt bearbeitet:
habs jetzt so gelöst :
Java:
	abstract class Class<T>{
		
	}
	class ClassChildWithString extends Class<String>{
		
	}
	interface ClassCollection<T,F extends Class<T>>{
		
		void doSomething(T t);
		
		void addList(ArrayList<F> list);
		
	}
	class ClassCollectionString implements ClassCollection<String,ClassChildWithString>{

		@Override
		public void doSomething(String t) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void addList(ArrayList<ClassChildWithString> list) {
			// TODO Auto-generated method stub
			
		}

	}
mich stört dabei :
interface ClassCollection<T,F extends Class<T>>
da F von T abhängt scheint es mir an dieser Stelle unschön...???
 
da F von T abhängt scheint es mir an dieser Stelle unschön...???
aber genau das ist doch, was du hier erzwingen willst oder etwa nicht? die abhängigkeit ist sowieso dadurch gegeben das ClassChildWithString<F> von Class<T> erbt
 
Zuletzt bearbeitet:
Ich habe hinterher NutzerKlassen welche bestimmte Methoden nutzen müssen welche das Interface bereitstellt.
Was innerhalb der der Spezialisierenden Klassen passiert hängt halt von T ab.
Nach aussen sollen sie aber da sie auf ähnlich aufgebauten UI - Elementen abgebildet werden sollen die (fast) gleiche Funktionalität anbieten.
Den Speicherklassen is nicht egal was für Elemente sie enthalten,da sich teilweise ganz andere Regeln durch die Art der enthaltenen Objekte ergeben.
In meinem Fall wäre es wohl einfacher gewesen die SpezialKlassen komplett unabhängig zu schreiben , allerdings hätte ich dann einigen Code doppelt und dreifach,was ich gerne vermeiden möchte !
 
Nach aussen sollen sie aber da sie auf ähnlich aufgebauten UI - Elementen abgebildet werden sollen die (fast) gleiche Funktionalität anbieten.

dann wäre der (aus meiner sicht) klügste ansatz, ein Interface für die UI Elemente zu entwerfen und dann deinen Objekten zusätzlich die Methoden für die jeweiligen Nutzerklassen beizubringen. das (fast) musst du dann natürlich irgendwie vereinheitlichen.

um doppelten code zu verringern kannst du für deine Objekte weitere interfaces erzeugen und abstrakte basisklassen für deine Objekte bereitstellen (quasi eine "Default"-variante wo das wesentliche gemeinsame drin ist)
 

Zurück
Oben