OOP Generics und Wildcards

membersound

Bekanntes Mitglied
Hallo,

bitte nicht über die (un)sinnigkeit des Codes wundern, habe versucht mein Problem soweit es geht zu reduzieren als Beispiel.


Die vererbte Klasse unterscheidet sich in einigen Membervariablen und zugehörigen getter+setter.
In einer Modellklasse erzeuge ich mehrere Objekte. Da ich jeden Typ getrennt brauche, sammel ich sie in zwei verschiedenen ArrayListen.

Wenn ich diese beiden ArrayListen nun ausgeben will, weiß ich aber nicht wie ich die Vererbung nutzen kann. Da printList(...) so wie in meinem Beispiel geschrieben ja verschiedene Datentypen erwartet.

Geht das nicht anders, oder kann man das doch noch so umschreiben, dass die Vererbung auch was vereinfacht?
Code:
public class NoteClass {


	private int a;

	public NoteClass(int a) {
		this.a = a;
	}

	public int getA() {
		return a;
	}

	static void printList(ArrayList<NoteClass> myList) {
		int sizeOfList = myList.size();
        	for (int i = 0; i < sizeOfList; i++) {
            		Note tmp = myList.get(i) 
			System.out.println(tmp.getA());
		}
	}
	
}

Code:
public class TaskClass extends NoteClass {

	private String b;

	public TaskClass(int a, String b) {
		super(a);
		this.b = b;
	}

	public String getB() {
		return b;
	}

	static void printList(ArrayList<TaskClass> myList) {
		int sizeOfList = myList.size();
        	for (int i = 0; i < sizeOfList; i++) {
            		Task tmp = myList.get(i) 
			System.out.println(tmp.getA() + tmp.getB());
		}
	}
	
}

Code:
public class MyModel {

	public MyModel() {

	ArrayList<NoteClass> myNoteList = new ArrayList<NoteClass>();
	ArrayList<TaskClass> myTaskList = new ArrayList<TaskClass>();

	NoteClass myNote = new NoteClass (1);
	TaskClass myTask = new TaskClass (2, "hallo");

	myNoteList.add(myNote);
	myTaskList.add(myTask);	

	NoteClass.printList(myNoteList);
	TaskClass.printList(myTaskList);
	}
}

Danke
 
Zuletzt bearbeitet:
Wenn du unterschiedliche Typen hast, dann hast du unterschiedliche Typen. Versuche nicht auf Biegen und Brechen einen gemeinsamen Obertyp zu finden.

Dein Codebeispiel hat mehrere Probleme. Ich möchte aber nicht auf alle eingehen, so lange ich nicht weiß was du mit dem Code genau bewirken möchtest.

Um Spezialisierungen in Unterklassen zu erreichen kannst du parametrisierte Typen benutzen:
Java:
class MyModel {

	public MyModel() {

		final ArrayList<NoteClass> myNoteList = new ArrayList<NoteClass>();
		final ArrayList<TaskClass> myTaskList = new ArrayList<TaskClass>();

		final NoteClass myNote = new NoteClass(1);
		final TaskClass myTask = new TaskClass(2, "hallo");

		myNoteList.add(myNote);
		myTaskList.add(myTask);
		
		myNote.printList(myNoteList);
		myTask.printList(myTaskList);
	}
}

abstract class SuperClass<T extends SuperClass<T>> {

	void printList(final ArrayList<T> myList) {
		final int sizeOfList = myList.size();
		for (int i = 0; i < sizeOfList; i++) {
			print(myList.get(i));
		}
	}

	abstract void print(T s);
}

class NoteClass extends SuperClass<NoteClass> {

	private final int a;

	public NoteClass(final int a) {
		this.a = a;
	}

	public int getA() {
		return a;
	}
	
	@Override
	void print(final NoteClass s) {
		System.out.println(s.getA());
	}
}

class TaskClass extends SuperClass<TaskClass> {

	private final String b;
	private final int a;

	public TaskClass(final int a, final String b) {
		this.a = a;
		this.b = b;
	}
	
	public int getA() {
		return a;
	}

	public String getB() {
		return b;
	}
	
	@Override
	void print(final TaskClass s) {
		System.out.println(s.getA()+s.getB());
	}
}
Das birgt aber mehrere Probleme. Du musst mit den konkreten Typen arbeiten und kannst nicht auf die Schnittstellen zurückgreifen. Eine Möglichkeit dies zu umgehen wäre, die Parametrisierung erst bei der Objektinstanziierung anzugeben. Um das zu ändern müsstest du aber noch genauer spezifizieren was du erreichen möchtest.
Weiterhin ist eine Klasse nicht dafür zuständig ihre eigene Kopien zu verwalten. In Java tust du dir am leichtesten, wenn du ein weiteres Objekt hast, das diese Aufgabe übernehmen kann:
Java:
class MyModel {

	public MyModel() {
		{
			final ArrayList<SuperClass> myNoteList = new ArrayList<SuperClass>();
			final ArrayList<SuperClass> myTaskList = new ArrayList<SuperClass>();
		
			final SuperClass myNote = new NoteClass(1);
			final SuperClass myTask = new TaskClass(2, "hallo");
		
			myNoteList.add(myNote);
			myTaskList.add(myTask);
			
			final SuperClassPrinter s = new SuperClassPrinter();
			s.printList1(myNoteList);
			s.printList1(myTaskList);
		}
		{
			final ArrayList<NoteClass> myNoteList = new ArrayList<NoteClass>();
			final ArrayList<TaskClass> myTaskList = new ArrayList<TaskClass>();

			final NoteClass myNote = new NoteClass(1);
			final TaskClass myTask = new TaskClass(2, "hallo");

			myNoteList.add(myNote);
			myTaskList.add(myTask);
			
			final SuperClassPrinter s = new SuperClassPrinter();
			s.printList2(myNoteList);
			s.printList2(myTaskList);
		}
	}
}

abstract class SuperClass {

	abstract void print();
}

class NoteClass extends SuperClass {

	private final int a;

	public NoteClass(final int a) {
		this.a = a;
	}

	public int getA() {
		return a;
	}
	
	@Override
	void print() {
		System.out.println(getA());
	}
}

class TaskClass extends SuperClass {

	private final String b;
	private final int a;

	public TaskClass(final int a, final String b) {
		this.a = a;
		this.b = b;
	}
	
	public int getA() {
		return a;
	}

	public String getB() {
		return b;
	}
	
	@Override
	void print() {
		System.out.println(getA()+getB());
	}
}

class SuperClassPrinter {
	void printList1(final ArrayList<SuperClass> myList) {
		final int sizeOfList = myList.size();
		for (int i = 0; i < sizeOfList; i++) {
			myList.get(i).print();
		}
	}
	
	<T extends SuperClass> void printList2(final ArrayList<T> myList) {
		final int sizeOfList = myList.size();
		for (int i = 0; i < sizeOfList; i++) {
			myList.get(i).print();
		}
	}
}
Je nach dem ob du darauf angewiesen bist mit Spezialisierungen zu arbeiten oder dich nur auf die Schnittstellen verlassen kannst, steht es dir frei die Methodensignatur von
Code:
printListX
zu ändern. Was für dich am besten ist hängt, wie bereits gesagt, von deinem Context ab.
 
Um Vererbung sinnvoll zu nutzen musst du natürlich auch ihre Vorteile anwenden:

Angenommen du hast eine Klasse Auto

Java:
class Auto{
	private int a;

	public Auto(int a) {
		this.a = a;
	}

	public int getA() {
		return a;
	}	
}

und eine Klasse Cabrio die von Auto erbt:
Java:
public class Cabrioextends Auto{

	private String b;

	public Cabrio(int a, String b) {
		super(a);
		this.b = b;
	}

	public String getB() {
		return b;
	}
}

Jetzt kannst du beide Objekte in einer einzigen Liste bearbeiten.
Java:
public class MyAutohandel{

	public MyAutohandel() {

	ArrayList<Auto> myAutoList= new ArrayList<Auto>();

	Auto a1= new Auto(1);
	Cabrio c1= new Cabrio (2, "hallo");

	myAutoList.add(a1);
	myAutoList.add(c1);	
	}
}

Wenn du jetzt deine Objekte z.b ausgeben willst, schreibst du eine Methode in Auto und überlagerst diese Methode in Cabrio.

Java:
class Auto{
	private int a;

	public Auto(int a) {
		this.a = a;
	}

	public int getA() {
		return a;
	}
public String toString()
{
  return String.valueOf(a);
}
	
}

und eine Klasse Cabrio die von Auto erbt:
Java:
public class Cabrioextends Auto{

	private String b;

	public Cabrio(int a, String b) {
		super(a);
		this.b = b;
	}

	public String getB() {
		return b;
	}

public String toString()
{
  return a+" "+b;
}
}
Dadurch kannst du beide Klassen mit der gleichen Methode ansprechen.
Java:
public class MyAutohandel{

	public MyAutohandel() {

	ArrayList<Auto> myAutoList= new ArrayList<Auto>();

	Auto a1= new Auto(1);
	Cabrio c1= new Cabrio (2, "hallo");

	myAutoList.add(a1);
	myAutoList.add(c1);	
     
        for(Auto help:myAutoList)
        {
               System.out.println(help.toString());
        }
}
}
 
Zuletzt bearbeitet:
Das ist super, und funktioniert auch in meinem Code und ist denk ich auch die beste Lösung.

Mein Problem war ja, dass ich die Objekte in unterschiedlichen ArrayList-Typen gesammelt habe, um deren print-Funktionen unterschiedlich aussehen zu lassen. Das geht ja jetzt :toll:
 

Neue Themen


Zurück
Oben