Vererbung und ArrayList mit Mutterklasse

Bitte aktiviere JavaScript!
es klappt (endlich), aber das kann unmöglich so richtig sein:
Java:
import java.util.ArrayList;

public class Tier {
   
    public String geschlecht;

    public static void main(String[] args) {
        ArrayList<Tier> tiere = new ArrayList<Tier>();
        tiere.add(new Fisch("w", "glatt", 4));
        tiere.add(new Saeugetier("m", 10, true));
        for (int x=0; x<tiere.size(); x++) {
            if (tiere.get(x).getClass().toString().contains("Fisch")) {
                Fisch f = (Fisch) tiere.get(x);
                System.out.printf("Fisch(%s, %d Flossen, %s Schuppen)", f.geschlecht, f.getflossenanzahl(), f.getschuppenart());
            } else if (tiere.get(x).getClass().toString().contains("Saeuge")) {
                Saeugetier s = (Saeugetier) tiere.get(x);
                System.out.printf("Säugetier(%s, %d Krallen, Fleischfresser %b)", s.geschlecht, s.getanzahlkrallen(), s.getistFleischfresser());
            } else {
                System.out.println("Fehler");
            }
            System.out.println();
        }
    }
}
Java:
public class Fisch extends Tier {
    private String schuppenart;
    private int flossenanzahl;
   
    public Fisch(String g, String s, int f) {
        super.geschlecht = g;
        this.schuppenart = s;
        this.flossenanzahl = f;
    }
   
    public String getschuppenart() {
        return this.schuppenart;
    }
    public int getflossenanzahl() {
        return this.flossenanzahl;
    }
}
Java:
public class Saeugetier extends Tier {
    private int anzahlkrallen;
    private boolean istFleischfresser;
   
    public Saeugetier(String g, int k, boolean f) {
        super.geschlecht = g;
        anzahlkrallen = k;
        istFleischfresser = f;
    }
   
    public int getanzahlkrallen() {
        return anzahlkrallen;
    }
    public boolean getistFleischfresser() {
        return istFleischfresser;
    }
}
Mein Problem war, dass ich in der ArrayList nicht auf die der Klasse des Objektes entsprechende Methoden zugreifen konnte, sondern nur auf die der Mutterklasse, obwohl ich mit getClass() die Klasse auslesen konnte.
Oder habe ich die Objekte falsch in die ArrayList gespeichert? Ich dachte man macht es so, wenn man mehrere Objekte in ein Array packen möchte, die eine gemeinsame Mutterklasse haben
 
A

Anzeige


Vielleicht hilft dir dieser Kurs hier weiter: (hier klicken)
Doch, das ist so richtig ;)
Der Compiler überprüft, ob alle Aufrufe passen, für Elemente in der Liste weiß er aber nur, das Tiere drin liegen, nicht welche, es gehen also nur Aufrufe von Methoden von Tier.
Mit dem casten sagst du ihm, dass du es besser weißt
 
Du kannst es auch bisschen anders lösen. Ich würde dir zum Beispiel raten, nicht die Logik in die Daten zu mischen (main method)

Für die Abfrage, welche Art von Tier es ist, kannst du auch instanceOf verwenden.
Dafür habe ich zwei extra Methoden spendiert.

Java:
public class MainZooExample {
    public static void main(String[] args) {
        Zoo zoo = new Zoo();
        zoo.fuelleTiere();
        zoo.listeTiereAuf();
    }
}
Java:
public class Zoo {
    private List<Tier> tiere;

    public Zoo() {
        tiere = new ArrayList<Tier>();
    }
 
    public void fuelleTiere() {
        tiere.add(new Fisch("w", "glatt", 4));
        tiere.add(new Saeugetier("m", 10, true));
    }
 
    public void listeTiereAuf() {
       // eine ForEach Schleife ohne Index
        for(Tier tier : tiere) {
            if(isFisch(tier) {
                Fisch fisch = (Fisch) tier;
            } else if(isSaeugetier(tier)) {
                Sauegetier saeugetier = (Sauegetier) tier;
            } else {

            }
        }
    }

    private boolean isFisch(Tier tier) {
        return tier instanceOf Fisch;
    }

    private boolean isSaeugetier(Tier tier) {
        return tier instanceOf Saeugetier;
    }
}
Java:
public class Tier {
    public String geschlecht;
}
 
danke Leute. ich bin froh, dass ich wenigstens das gecheckt habe.
ich hatte alles in die main "gestopft", weil eh nur ein test war.
@Jardcore die 2 Unterklassen Fisch und Saeugetier sind gleich geblieben, weil hier nicht aufgeführt?
Anmerkung: ich finde es seltsam, dass man in einen Typ casten muss, obwohl das Objekt nachweislich bereits diesen Typ hat. Daher meine Ungläubigkeit/Frage.
EDIT: netbeans meckert bei mir bei List<Tier> tier = new ArrayList<Tier>; und ich muss direkt ArrayList<Tier> tier = new ArrayList<Tier>; schreiben. seltsam.
 
Zuletzt bearbeitet:
Anmerkung: ich finde es seltsam, dass man in einen Typ casten muss, obwohl das Objekt nachweislich bereits diesen Typ hat. Daher meine Ungläubigkeit/Frage.
Ja, das lösen andere Sprachen schöner...

EDIT: netbeans meckert bei mir bei List<Tier> tier = new ArrayList<Tier>; und ich muss direkt ArrayList<Tier> tier = new ArrayList<Tier>; schreiben. seltsam.
Ersteres ist genauso richtig (mit dem richtigem List-import), allerdings fehlen bei beiden die Klammern ;)
 
die 2 Unterklassen Fisch und Saeugetier sind gleich geblieben, weil hier nicht aufgeführt?
Ja, so ist es.

Ich persönlich hätte vielleicht noch die Tier Klasse etwas mehr verändert. Und dann müsstest du auch die Unterklassen ändern. Hier mal Am Beispiel Fisch. Ich würde auch im Konstruktor die Namen aussschreiben. Getter und Setter werden übrigens auch im CammelCase geschrieben. getEinWert()

Java:
public class Tier {
    private String geschlecht;

    public Tier(String geschlecht) {
        setGeschlecht(geschlecht);
    }
    public void setGeschlecht(String geschlecht) {
        this.geschlecht = geschlecht;
    }

    public String getGeschlecht() {
        return geschlecht;
    }
}
Java:
public class Fisch extends Tier {
    private String schuppenart;
    private int flossenanzahl;
  
    public Fisch(String geschlecht, String schuppenart, int flossenanzahl) {
        super(geschlecht);
        this.schuppenart = schuppenart;
        this.flossenanzahl = flossenanzahl;
    }
  
    public String getSchuppenart() {
        return this.schuppenart;
    }
    public int getFlossenanzahl() {
        return this.flossenanzahl;
    }
}
 
kann ich erst beantworten, wenn ich zuhause bin. aber wenn es wurscht ist, bleibe ich beim
ArrayList<> var = new ArrayList<>()
EDIT: wo ist der Unterschied zwischen super.geschlecht = geschlecht; und super(geschlecht);, außer, dass das letztere den Mutter-Konstruktor benutzt?
 
Zuletzt bearbeitet:
Moin,
wo ist der Unterschied zwischen super.geschlecht = geschlecht; und super(geschlecht);, außer, dass das letztere den Mutter-Konstruktor benutzt?
eben genau in der Benutzung des Konstruktor, d. h. Du rufst hier den Konstruktor auf mit Übergabe des Werts geschlecht!
Im ersten Fall wird nur der Wert der Variable super.geschlecht gesetzt ... Im Konstruktor könnten ja theoretisch noch weitere Aktionen ausgeführt werden !!

Gruß Klaus
 
kann ich erst beantworten, wenn ich zuhause bin. aber wenn es wurscht ist, bleibe ich beim ArrayList<> var = new ArrayList<>()
Es ist nicht Wurscht, man sollte bei der Deklaration immer das Interface verwenden, da du dann nicht an die Implementierung gebunden bist. Du könntest zum Beispiel die ArrayList einfach durch eine LinkedList tauschen.
 
ich habe nun die Lösung, die ich auch für meine Kartenspiel-Programme so umsetze.
Verschiedene Kartentypen habe ich jetzt nicht als Unterklasse einer Klasse Karte erstellt, sondern alle Karten haben die selbe Klasse Karte, aber - wegen unterschiedlicher Attribute - unterschiedliche Konstruktoren. Somit ist das casten unnötig geworden, weil sich nurnoch Objekte der Klasse Karte in der ArrayList befinden. Letztlich funktioniert beides, aber ich finde das so viel eleganter.
An das Überladen von Konstruktoren hatte ich ja vorher garnicht gedacht.
 
Okay, es ging also nicht um Fische? :)
Das ist aber leider eine schlechte Lösung, so hast du Daten in der Karten Klasse die dort einfach nicht hingehören. Zumindenstens wenn es Unterschiede im Ausmaß des Fischbeispiels sind.
 
ich habe nun die Lösung, die ich auch für meine Kartenspiel-Programme so umsetze.
Verschiedene Kartentypen habe ich jetzt nicht als Unterklasse einer Klasse Karte erstellt, sondern alle Karten haben die selbe Klasse Karte, aber - wegen unterschiedlicher Attribute - unterschiedliche Konstruktoren. Somit ist das casten unnötig geworden, weil sich nurnoch Objekte der Klasse Karte in der ArrayList befinden. Letztlich funktioniert beides, aber ich finde das so viel eleganter.
An das Überladen von Konstruktoren hatte ich ja vorher garnicht gedacht.
Wir haben im Studium gerade eine ähnliche Aufgabe zu lösen. Könntest du deine Lösung posten? Bin sehr gespannt.
 
Wir haben im Studium gerade eine ähnliche Aufgabe zu lösen. Könntest du deine Lösung posten? Bin sehr gespannt.
Mach besser einen neuen Thread auf, anstatt 2 Jahre alte Leichen auszugraben. Und beschreibe dabei, wo Dein Problem liegt und was Du schon versucht/Dir überlegt hast.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben