Problem mit ArrayList - Typen innerhalb der ArrayList

Also es ist so: AbstrakterMario hat ja jetzt keinen Default-Konstruktor, da du ja einen anderen Konstuktor explizit deklariert hast. Da die abgeleiteten Klassen in der in der Call-Hierarchie entsprechend einen Konstruktor der Vaterklasse aufrufen wollen und der Default-Konstruktor per Default auch nur den Default-Konstruktor der Vaterklasse aufruft, haben die Klassen jetzt ein Problem, denn es gibt diesen Default-Konstruktor nicht in AbstrakterMario und somit weiß jetzt der Default-Konstruktor (z.B. von SuperMario) nicht, was er machen soll. Das heißt du musst jetzt auch in den abgeleiteten Klassen die entsprechenden Konstruktoren explizit implementieren, wobei das eigentlich eher egal ist, es geht nur um den Aufruf. Aber sinnvoller Weise würde es ja Sinn machen, wenn man die Konstruktoren auch mit sinnvollen Werten füttert und nich mit fiktivem Mist und diese Werte bekommst du eben durch einen entsprechenden Konstruktor.

So, jetzt könnte man sich natürlich fragen, warum dann überhaupt in AbstrakterMario schon einen Konstruktor deklarieren, wenn ich in den Subklassen eh wieder die Konstruktoren deklarieren muss. Ganz einfach, weil die Konstruktoren der abgeleiteten Klassen anders aussehen. Die eigentliche Arbeit macht immer noch der Konstruktor von AbstrakterMario, die Konstruktoren der Subklassen leiten den Aufruf nur weiter, haben aber an sich keinen sinnvollen Code (außer FlugMario, da er ja noch die Flugzeit bekommt).

Das sieht dann so aus:
Java:
public class SuperMario extends AbstrakterMario {
	public SuperMario(boolean gross, int leben) {
		super(gross, leben);
	}
}

Das ist der ganze Trick dabei. Bei FlugMario sieht der Konstruktor dann etwas anders aus, weil er noch einen weiteren Parameter hat. Aber auch da wird einfach per super() der Vaterkonstruktor aufgerufen, nur musst du dann halt noch das mit der Flugzeit managen.
 
Zuletzt bearbeitet:
kann es dann sein, das wenn KEIN konstruktor vorhanden ist, im hintergrund default konstruktor aber da ist, aber sobald ich einen konstruktor schreibe, dieser nicht mehr da ist?
weil diese fehlermeldung kam halt sobald ich in der abstrakten klasse nen konstruktor mit reingenommen hab.

ja das mit dem super() hab ich schon grad rausgefunden, das ist echt ne toll mit dem super().
für flugmario hab ich
Code:
	public FlugMario(boolean größe, int leben,int flugzeit)
	{
		super(größe,leben);
		this.flugzeit=flugzeit;
	}


Nur beim werfen häng ich jetz grade, aber das schaff ich au noch, dann hab ichs fertig
 
Ja, genau so ist es auch. Wenn du keinen Konstruktor deklarierst, dann übernimmt das Java und deklariert selbst einen Default-Konstruktor. Der macht einfach nix, aber man braucht eben immer einen Konstruktor, wenn man man von Klassen Instanzen erzeugen will. Sobald du aber explizit einen Konstruktor deklarierst, deklariert Java keinen Default-Konstruktor mehr. Macht ja auch Sinn, denn es kann ja sein, dass man gar nicht will, dass man eine Instanz der Klasse über den Default-Konstruktor erzeugen will, sondern dass immer ein ganz bestimmter Parameter übergeben werden muss. Das ist also schon gewollt so.

EDIT:
Ja, an dem Werfen überlege ich auch grad. Mir fallen spontan drei Möglichkeiten ein, wie man das umsetzen kann. Die Frage ist, auf welche Weise es "besser" ist, wobei das eigentlich eher uninteressant ist. Viel mehr würde mich interessieren, was sich dein Prof bei der Aufgabe gedacht hat. Er wird ja eine Vorstellung davon gehabt haben und somit auch eine Beispiellösung parat haben. Die Frage ist also, in welche Richtung diese geht.
 
Zuletzt bearbeitet:
Ok, dann danke ich dir mal für deine erklärungen :)
aber mit dem werfen komm ich nicht voran ... kann die werfen methode ja nicht in die abstrakte reintun, weil der pinguin diese nicht kennen darf.
gleichzeitig ist aber in der abstrakten methode die sammeln methode drin, welche die panzeranzahl verwaltet.
so kann ich, wenn ich werfen() in die unterklasse tu, nicht auf die panzerzahl zugreifen ...
mache ich nun aber beide methoden abstract, und implementiere diese später, musste ich wieder instanzvariablen leben und größe in die unterklasse mit aufnehmen, da wenn ein grüner/roter pilz gesammelt wird sich diese variablen verändern.....


//Edit: hm, habs jetz am laufen, hab das sammeln/werfen mit in der abstrakten klasse und hab dann in den methoden mit na if abfrage den fall das es auf ein pinguin objekt ausgeführt wird ausgeschlossen .... aber der sinn der sache ist das glaub ich nicht ^^

Lösung bekomme ich erst nächsten freitag.
Also wir haben grade als thema halt abstrakte klassen, polymorphismus, interfaces. grade angefangen. und nach den erklärungen vom prof hin, darf die nach diesem beispiel die klasse pinguinmario die funktion werfen auf keinen fall kennen, was meine jetzige lösung ja zunicht macht
 
Zuletzt bearbeitet:
Ich habe das mit dem Werfen noch nich gemacht, aber kann dir ja mal meine Ideen verraten.

1. Man nimmt die Methode werfen() mit in AbstrakterMario auf und implementiert sie sogar aus, da SuperMario und FlugMario die Panzer ja werfen können. Bei PinguinMario wird die Methode dann überlagert, allerdings mit einem leeren Methodenkörper, sprich sie macht nix. Aber da ist das Problem, das du bereits erkannt hast. Ich habe die Aufgabe auch so verstanden, dass PinguinMario die Methode gar nicht kennen darf, das wäre aber bei diesem Ansatz der Fall.

2. Man bastelt sich ein Interface Werfen oder so, das die Methode werfen() deklariert. Das Interface wird von SuperMario und FlugMario implementiert und somit auch die Methode werfen(). Auf das Interface kann man eigentlich auch verzichten, aber so hat man es einheitlich und könnte dann sogar über das Interface agieren ohne zu wissen, welcher Mario-Typ da eigentlich verwendet wird.

3. Ist eigentlich wie 2, aber anstatt eines Interfaces wird jetzt eine weitere abstrakte Klasse WerfenderMario deklariert, welche die Methode werfen() deklariert und sogar implementiert. Die Klasse wird von AbstrakterMario abgeleitet und SuperMario und FlugMario wiederum leiten von WerfenderMario ab. Die Klasse WerfenderMario ist deswegen abstrakt, weil sie nicht zur Instanziirung gedacht ist, sondern nur eine Schnittstellenfunktion erfüllen soll und somit die ableitenden Klassen nur um weitere Funktionalitäten erweitert.

Die sauberen Lösungsansätze sind 2. und 3., da 1. eher gepfuscht ist und laut Aufgabenstellung meiner Meinung nach die Aufgabe auch nicht erfüllt ist. Durch die Ansätze 2. und 3. ist gegeben, dass PinguinMario die Methode werfen() nicht kennt, die anderen beiden Marios aber schon (wie es nach meinem Verständnis in der Aufgabe gefordert ist). Im Ansatz 2. verändert sich an der ursprünglichen Umsetzung (also ohne Ansatz 1.) eigentlich soweit nichts, es kommt nur ein Interface hinzu. Beim Ansatz 3. wird die Vererbungshierarchie etwas abgeändert, indem WerfenderMario mitten in die Hierarchie eingehangen wird. In der Aufgabe stand nichts davon, dass sowas verboten sei, müsste also erlaubt sein und wäre sogar die beste Umsetzung. Allerdings stört mich an der Variante etwas, ich weiß gerade nur nicht was ...
 
Zuletzt bearbeitet:
ich werd wenn ich die lösung bekomme diese heir mal posten, dann kanns du dir angucken wie er sich das vorgestellt hat. an ein interface hab ich auch schon gedacht, aber letzte mal war mein interface auch nur "unnötig" und "nicht gefordert" ...

Edit:
Ich habe mich deiner dritten lösung mal angenommen:

aus AMario hab ich die private int panzer und die methode schmeißen rausgenommen, die sammeln method etwas modifiziert:
Code:
public void sammeln(AGegenstand gegenstand)
	{
		if(gegenstand.getClass()==RoterPilz.class)
		{
			this.größe=true;
			System.out.println(this.getClass().getName() + " wächst");
		}
		else if(gegenstand.getClass()==GrünerPilz.class)
		{
			this.leben++;
			System.out.println(this.getClass().getName() + " erhält ein Leben");
		}
	}
das hier ein else if ist ist gewwollt. der gegenstand könnte ja auch panzer sein. das wird heir aber noch nicht geprüft, dazu später mehr.


dann habe ich die abstrakte klassse ASchmeißenderMario, wenn ich das mit dem super richtig verstanden hab wird meine sammeln methode hier in der art erweitert?:
Code:
public abstract class ASchmeißenderMario extends AMario{
	
	private int panzer;
	
	public void schmeißen()
	{
		System.out.println(this.getClass().getName() + " wirft einen Panzer");
		this.panzer--;	
	}
	
		public void sammeln(AGegenstand gegenstand)
	{
		super.sammeln(gegenstand);
		if(gegenstand.getClass()==Panzer.class)
		{
			if(this.panzer<3)
			{
				System.out.println(this.getClass().getName() + " sammelt einen Panzer");
				this.panzer++;
			}
			else
			{
				System.out.println(this.getClass().getName() + " hat schon 3 Panzer");

			}
		}

	}
hier wird dann auch auf panzer geprüft

Das sollte soweit meiner Meinung nach alles ok sein.
Jetzt leitet sich ja die abstrakte klasse ASchmeißenderMario von AMario ab, die kenns du ja insoweit schon.
Da ich mit dem super so noch keinen kontakt hatte habe ich jetzt ein kleines problem :
Du hast mir ja sowas hier gezeigt:
Code:
public class Mario extends ASchmeißenderMario{
	

	public Mario(boolean größe, int leben)
	{
		super(größe,leben);
	}

jetzt ist Mario ja aber in der ableitungsherachie weiter unten, ASchemißenderMario hat keine instanzvariablen außer dem panzer, daher könnte ich dort diesen konstruktor ja nicht vordefinieren, weshalb ich auch auf AMario weiter zugreifen muss.
Aber wie? Ich dachte jetzt an sowas wie super.super(größe,leben) oder super (super(größe,leben)) aber das ist wohl nicht die richtige syntax, falls sowas in der art möglich ist .. ^^



Edit 2:
Ok, musste in ASchmeißenderMario auch noch
Code:
public ASchmeißenderMario(){};
	
	public ASchmeißenderMario(boolean größe, int leben)
	{
		super(größe,leben);
	}
einfügen .... hat sich also erledigt :)

Könntest mir nur gerne noch bestätigen das das mit dem sammeln in AWerfenderMario mit dem super so richtig ist, also ich denke, das die methode mit gleichem parameter halt erst auf roter pilz oder grüner pilz prüft, wie in der superklasse halt die sammelmethode ist, und danach noch was zusätzliches ausgeführt wird, halt das prüfen auf einen panzer, was aber halt durch die vererbungsherachie nur in Mario/Flugmario getan wird.


Hm ... Wenn ich mir meine eigenen texte hier so durchlese kann ich ziemlich schlecht im bezug auf programmierung erklären was ich meine xd
 
Zuletzt bearbeitet:
Doch doch, das ist richtig so ^^ Zuerst wird die Original-Methode ausgeführt und dann dein dazugebastelter Teil.

Sorry, aber ich kann grad nicht so wirklich viel erklären oder helfen, hab mir meine linke Hand verbrüht und das tut höllisch weh, daher ist das jetzt auch nur so kurz.
 
Zurück