generische ArrayList -> erbende Objekte auslesen

bluerob

Mitglied
Hallo liebe Community,

mein Titel ist leider nicht genau, aber mir ist leider nichts besseres eingefallen ;)

Habe folgendes Problem:

Ich habe eine generische ArrayList<Einheit> erstellt, und dieser Objekte hinzugefügt.
Die Objekte
  • sind aus unterschiedlichen Klassen
  • haben unterschiedliche Attribute/Methoden (siehe Punkt vorher)
  • erben allesamt von der Klasse Einheit
Der letzte Punkt ist der Grund, weshalb ich die ArrayList auf Einheit definiert habe, da diese schließlich die Oberklasse aller Objekte ist.

Wenn ich jetzt meine ArrayListe auslesen möchte, kann ich natürlich nur die Methoden, dementsprechend auch nur die Attribute, von Einheit auslesen, aber bräuchte auch Zugriff auf die Methoden der Unterklassen.

Hoffe ihr versteht mein Problem und könnt mir helfen.
Hier noch bissi Quelltext zum Verständnis:

Java:
public class Staffel {
 
    private ArrayList<Einheit> staffel = new ArrayList<Einheit>();
    private Magier magier;
    private Krieger krieger;
    private Bogenschütze bogenschütze;

...

public void addMagier(String rang){
        if(anzEinheit<10){
            magier = new Magier("Magier","rang",20,1,1,40);
            staffel.add(magier);
            anzEinheit++;
        }else System.out.println("Die Staffel ist voll besetzt");
    }

// selbe Methode auch für Krieger und Bogenschütze

...
 
public void ausgabeStaffel(){
        for(int i=0;i<=anzEinheit;i++){
            staffel.get(i). 
// Hier sollen alle Attribute von Magier ausgegeben werden, da Mana allerdings über die Methode .getMana() aus der Klasse Magier ausgelesen wird, kann ich das Attribut nicht bekommen.
        }
    }

public class Magier extends Einheit{

    private int mana;

    public Magier(String sorte, String rang,int leben, int geschick, int verteidigung, int mana) {
        super(sorte, rang, leben, geschick, verteidigung);
    }
 

Xeonkryptos

Bekanntes Mitglied
Java:
public class Staffel {

	private ArrayList<Einheit> staffel = new ArrayList<Einheit>();
	private Einheit einheit;
	private Magier magier;
	int anzEinheit = 0;

	public void addMagier(String rang) {
		if (anzEinheit < 10) {
			magier = new Magier("Magier", "rang", 20, 1, 1, 40);
			staffel.add(magier);
			anzEinheit++;
		} else
			System.out.println("Die Staffel ist voll besetzt");
	}

	// selbe Methode auch für Krieger und Bogenschütze

	public void ausgabeStaffel() {
		for (int i = 0; i < anzEinheit; i++) {
			einheit = staffel.get(i);
			System.out.println(((Magier) einheit).getMana());
		}
	}
}

So müsste dein Code aussehen. Du musst den Inhalt aus dem Array zwischenspeichern, das heißt, ihn in eine Variable vom Typ Einheit übertragen und diese dann casten. Durch das Casten sagst du, dass die Methode aus der Klasse Magier zu nehmen ist und nicht aus der Klasse Einheit, da der Magier eine Einheit ist, ist dies hier durch die Polymorphie ohne Probleme möglich. Die Ausgabe kannst du ignorieren, da es nur ein Test war. Das wichtige an dem Code ist:
Java:
((Magier) einheit).getMana());

Und beachte, bei deinem Code wird IMMER(!) eine IndexOutOfBoundsException fliegen, da deine Überprüfung des Schleifenübergangs fehlerhaft bzw schlecht ist. Wenn du bei 0 beginnst und ein Array auslesen willst, musst du IMMER "<" hinschreiben, da du ansonsten eine Stelle weiterüberprüfst, die gar nicht im Array existiert, weil es nicht so groß ist. Wenn du bei 1 beginnst, ist "<=" zu empfehlen, hier aber nicht!
 

Marco13

Top Contributor
Eigentlich ganz einfach:
Java:
Einheit einheit = eineEinheit;
if (einheit instanceof Magier)
{
    Magier magier = (Magier)einheit;
    magier.getMana();
}
if (einheit instanceof Krieger)
...

AAAABER: IMMER wenn man 'instanceof' verwendet, sollte man GENAU überlegen, ob man nicht gerade etwas ganz gravierend falsch macht. (Manchmal kommt man zu dem Schluss: Nein. Aber man sollte es sich IMMER GENAU überlegen). Ein wichtiges Problem mit instanceof ist, dass man es schlecht erweitern kann. Wenn später noch eine Klasse "Elf" hinzukommt, muss vielleicht an allen Stellen, wo instanceof verwendet wird, etwas aktualisiert werden (vielleicht weil ein Elf auch ein Mana hat, oder dort dann eine andere Abfrage gemacht werden muss...).

In diesem Fall: Warum braucht man an dieser Stelle (in ausgabeStaffel) die Information, dass es ein Magier ist? Wäre es vielleicht sinnvoll, explizit eine Liste<Magier> irgendwo zu speichern? Wäre es vielleicht besser, wenn die Methode 'getMana' in der Klasse "Einheit" stehen würde, und bei einem Krieger einfach "0" zurückgibt? (Vermutlich nicht, nur ein Denkanstoß!).

Es sollte wann immer möglich nur das Interface verwendet werden. Genauso wie bei "List":
private ArrayList<Einheit> staffel = new ArrayList<Einheit>();
ändern in
private List<Einheit> staffel = new ArrayList<Einheit>();
;)


EDIT: In diesem Fall könnte es noch eine Möglichkeit geben, die in genau dieser Form auch nicht sinnvoll ist, aber vielleicht eine Richtung aufzeigt: Das interface "Einheit" könnte eine Methode haben wie "gibDichAus". Dann würde man diese Methode im Magier so implementieren:
Java:
class Magier implements Einheit
{
    private int mana;

    public void gibDichAus()
    { 
        System.out.println("Magier mit "+mana);
    }
und im Krieger z.B. so
Java:
class Krieger implements Einheit
{
    private boolean hatSchild;

    public void gibDichAus()
    { 
        System.out.println("Krieger mit Schild? "+hatSchild);
    }

(Nochmal: Das ist so NICHT sinnvoll, soll nur verdeutlichen, dass man so evtl. die "Richtung" umdrehen kann, und das notwendige Wissen in die Implementierung legen und dadurch die Polymorphie ausnutzen kann)
 
Zuletzt bearbeitet:

bluerob

Mitglied
((Magier) einheit).getMana());

Hiermit klappt alles wunderbar! Danke! :)

AAAABER: IMMER wenn man 'instanceof' verwendet, sollte man GENAU überlegen, ob man nicht gerade etwas ganz gravierend falsch macht. (Manchmal kommt man zu dem Schluss: Nein. Aber man sollte es sich IMMER GENAU überlegen). Ein wichtiges Problem mit instanceof ist, dass man es schlecht erweitern kann. Wenn später noch eine Klasse "Elf" hinzukommt, muss vielleicht an allen Stellen, wo instanceof verwendet wird, etwas aktualisiert werden (vielleicht weil ein Elf auch ein Mana hat, oder dort dann eine andere Abfrage gemacht werden muss...).

Das muss ich mir noch mal durch den Kopf gehen lassen. Es stimmt schon, dass meine Klassen nicht sehr dynamisch sind. Danke für den Tipp!
 

Marco13

Top Contributor
Hiermit klappt alles wunderbar! Danke! :)

Vorsicht: Das funktioniert natürlich NUR wenn in der Liste auch wirklich NUR Magier stehen. Wenn dort auch ein Krieger drinsteht, schmeißt er eine ClassCastException. (Und wenn du wüßtest, dass immer NUR Magier drinstehen, könntest du sie gleich als List<Magier> deklarieren - aber das ist wohl nicht der Fall...)
 

Xeonkryptos

Bekanntes Mitglied
Vorsicht: Das funktioniert natürlich NUR wenn in der Liste auch wirklich NUR Magier stehen. Wenn dort auch ein Krieger drinsteht, schmeißt er eine ClassCastException. (Und wenn du wüßtest, dass immer NUR Magier drinstehen, könntest du sie gleich als List<Magier> deklarieren - aber das ist wohl nicht der Fall...)

stimmt. Da müsste man noch das "instanceof" davorschieben oder eine eher unschöne Lösung wäre ein try-catch-Block darum und die ClassCastException abfangen, dass er dann, wenn es fliegt, die Möglichkeit hat, es nach den anderen Klassen zu prüfen.
 

bluerob

Mitglied
Java:
einheit = staffel.get(i);
sorte = einheit.getSorte();

if(sorte.equals("Magier")==true)System.out.println("Mana: "
            +((Magier)einheit).getMana());

else if(sorte.equals("Krieger")==true)System.out.println("Kraft: "
            +((Krieger)einheit).getKraft());

else if(sorte.equals("Bogenschütze")==true)System.out.println("Pfeile: "
            +((Bogenschütze)einheit).getPfeile());

Hab es so gemacht, da ja im Konstruktor von Einheit die Sorte mitgegeben werden muss.
Ist das eine schlampige Lösung?
 

Xeonkryptos

Bekanntes Mitglied
Ich finde das nicht als eine schlampige Version, außer, dass du die Prüfung auf "true" weglassen kannst.
Java:
if(sorte.equals("Magier"))
Das kommt auf genau dasselbe hinaus und sieht noch schöner aus :)

ggf könntest hier auch mit Konstanten und dem Switch-Statement arbeiten oder wenn du java7 schon verwendest das in einem switch einbauen.
Im Endeffekt kannst du dir auch die Speicherung in eine zusätzliche Variable sparen, wenn du es so machst:
Java:
if(einheit.getSorte().equals("Magier"))
 

Marco13

Top Contributor
Ist das eine schlampige Lösung?

Ich finde schon... Zumindest ist es nicht besser oder flexibler als das instanceof, genauso schlecht erweiterbar und stattdessen eher anfällig für (Tipp-) Fehler (Strings werden nicht zur Compilezeit geprüft).

Irgendwann wollte ich schon mal (oder habe ich das schon?) einen Philosophier-Thread eröffnen, zu den Möglichkeiten und Notwendigkeiten in diesem Bereich. Ich glaube ja, dass man theoretisch IMMER auf Typabfragen jeglicher Form verzichten kann - es aber nicht wirklich so strikt praktikabel ist. Grundsätzlich hat man verschiedene Möglicheiten:
1. Eine Typinformation wie getType(), die einen int, Enum oder String liefert
2. Eine Abfrage mit instanceof
3. Irgendeine Abfrage, ob die gewünschte Funktionalität vorhanden ist
4. Die eventuell vorhandene Methode ins Interface mit aufnehmen
5. Alles ganz anders machen ;)


Das 1. hast du jetzt. Das 2. und 4. hatte ich schon angedeutet. Das 3. könnte grob so gemacht werden, wie z.B. das "Quakverhalten" in diesem Buch.

Das 5. zielt nochmal auf die Frage ab: Wazu genau brauchst du dort die Unterscheidung? Wenn es NUR um diese Ausgabe geht: Überschreib' bei deinen Klassen die "toString"-Methode vernünftig, und gut ist... Wenn es um VIEL mehr geht, könnte man auch in Erwägung ziehen, sich ausgefeiltere Strukturen dafür zu überlegen...
 

bERt0r

Top Contributor
Es wäre auch möglich, in deiner Einheit Klasse eine Map<Attribut,Object> zu speichern, wobei Attribut dann z.B eine Enum sein kann. Das wäre sehr erweiterbar, wenn du dann z.B ein Katapult machst, das eine Spezialfähigkeit Flächenangriff hat, steht einfach bei Katapult als Attribut: Flächenangriff als Wert(z.b Radius): 3 drin. Wenn du dann prüfen willst, ob eine beliebige Einheit einen Flächenangriff hat, machst du einfach if(attributMap.get(Flächenangriff)!=null).
 

Landei

Top Contributor
Java:
einheit = staffel.get(i);
sorte = einheit.getSorte();

if(sorte.equals("Magier")==true)System.out.println("Mana: "
            +((Magier)einheit).getMana());

else if(sorte.equals("Krieger")==true)System.out.println("Kraft: "
            +((Krieger)einheit).getKraft());

else if(sorte.equals("Bogenschütze")==true)System.out.println("Pfeile: "
            +((Bogenschütze)einheit).getPfeile());

Hab es so gemacht, da ja im Konstruktor von Einheit die Sorte mitgegeben werden muss.
Ist das eine schlampige Lösung?

In Java 7 ginge:

Java:
switch(einheit.getSorte()) {
  case  "Magier" : 
       System.out.println("Mana: " +((Magier)einheit).getMana()); break;
  case "Krieger" :
       System.out.println("Kraft: " +((Krieger)einheit).getKraft()); break;
  case "Bogenschütze" :
       System.out.println("Pfeile: " +((Bogenschütze)einheit).getPfeile()); break;
  default :
       System.out.println("Kenne ich nicht");
}
 

bERt0r

Top Contributor
Nicht so gut, wenn Die Map Mappings auf null erlaubt. Besser ist
[Java]
attributMap.containsKey("Flächenangriff");
[/Java]

Das != null wirst du dir aber nicht ersparen wenn du den Wert auslesen willst. In dem Flächenangriff Fall - ja ich weis dass ein ä wohl nicht als enum durchgeht :
Java:
Integer i=(Integer)attributMap.get(Flächenangriff);
if(i!=null)
{
//Mach flächengangriffscode
}
Und im Fall der Ausgabe kann man sowieso einfach drüberiterieren.
 

Marco13

Top Contributor
Vielleicht sollte ich nochmal erwähnen, dass die Ansätze 1.-3. (und die meisten, auf die bisher sonst so hingewiesen wurde) nichts mit OOP zu tun haben... Man muss sich nur überlegen, an wie vielen Stellen do eine Typabfrage u.U. nötig sein könnte, und wie man das warten sollte...
 
B

bygones

Gast
Vielleicht sollte ich nochmal erwähnen, dass die Ansätze 1.-3. (und die meisten, auf die bisher sonst so hingewiesen wurde) nichts mit OOP zu tun haben... Man muss sich nur überlegen, an wie vielen Stellen do eine Typabfrage u.U. nötig sein könnte, und wie man das warten sollte...
und wenn die Klassen nicht in ein einheitliches Schema zusammengefasst werden koennen, so ist es auch nicht sinnig dies zu tun.
 

Marco13

Top Contributor
Falls sich das auf das hier bezieht:
Wäre es vielleicht sinnvoll, explizit eine Liste<Magier> irgendwo zu speichern?

Das ist natürlich auch nicht "gut", weil es sich nicht auf beliebige weitere Einheiten erweitern läßt. Eine Möglichkeit, das "instanceof" in generischer und leicht erweiterbarer Weise zu antizipieren wäre sowas wie
Java:
class Staffel
{
    public static void main(String[] args)
    {
        Staffel s = new Staffel();
        s.add(new Magier());
        s.add(new Krieger());
        s.add(new Magier());
        System.out.println("Alle  : "+s.getEinheiten());
        System.out.println("Magier: "+s.get(Magier.class));
    }

    private List<Einheit> einheiten = new ArrayList<Einheit>();

    public List<Einheit> getEinheiten()
    {
        return Collections.unmodifiableList(einheiten);
    }

    public void add(Einheit e)
    {
        einheiten.add(e);
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> get(Class<T> c)
    {
        List<T> result = new ArrayList<T>();
        for (Einheit einheit : einheiten)
        {
            if (c.isAssignableFrom(einheit.getClass()))
            {
                result.add((T) einheit);
            }
        }
        return Collections.unmodifiableList(result);
    }
}

(Das könnte man ggf. auch ein eine statische Utility-Methode wie
<T> List<T> filter(Iterable<T> i, Class<T> c)
auslagern). Ich finde das auch nicht so schön, und es wäre IMHO besser, wenn man sich über die Anforderungen und das Einheits-Interface (sic :D) im Klaren wäre, aber... zumindest eine Option...
 

bluerob

Mitglied
Erstmal danke für das ganze Engagement! :)

Hab zurzeit leider nicht so viel Zeit, aber ab morgen werde ich mich hoffentlich wieder hinter mein Projekt klemmen können.
Trotzdem habe ich mir alles durchgelesen und festgestellt, dass ich vieles noch nicht verstehe. Werde also den größten Teil eurer Antworten erstmal recherchieren müssen. Aber so lernt man wenigstens Neues :)

Nochmal zur Erklärung um was es eigentlich geht.
Der Plan es folgendermaßen: Ich möchte eine Art Kampfsimulator programmieren.

Es kämpfen verschiedene Staffeln gegeneinander. Damit der Kampf dynamisch ist, möchte ich, dass man beliebig viele Staffeln hinzufügen kann. Einzige Bedingung hierbei ist, dass eine Staffel aus 10 Einheiten besteht. Dabei ist aber nicht festgeschrieben, welche Einheiten dies sind! Es können also auch einfach 10 Magier sein oder 5 Krieger und 5 Bogenschützen.

Da ich OOP möchte, habe ich die Überklasse Einheit gemacht. Schließlich haben sowohl Magier, als auch Krieger Leben. Zusätzlich haben die Subklassen dann zusätzliche Attribute und Methoden (z.B. Skills).

Die einzelnen Staffeln werden später von meinem Simulator ausgelesen. Deshalb habe ich eine ArrayListe<Einheit>, welche als Staffel dienen soll. Hier ergibt sich mein Problem mit dem Auslesen, da ich nicht auf die spezifischen Unterklassen Attribute/Methoden zugreifen kann. Außer ich gehe über diesen Weg: ((Krieger)einheit). (Wie nennt man diese Vorgehensweise?) Aber hier ist das Problem, dass mein Projekt dadurch an der Stelle sehr festgefahren wird.

Zusammengefasst:
  • Staffel Vs Staffel
  • Staffel<=10
  • Staffel besteht aus unterschiedlichen Einheiten
  • Simulator liest -> ArrayList<Einheit> = Staffel <- behinhaltet Objekte der Subklassen von Einheit

Das ist eigentlich so der Plan :)

Dynamische Programmierung ist meiner Meinung nach sehr schwierig und man drückt sich auch gern davor, aber ich würde gern versuchen, mein Projekt so zu verwirklichen, dass ich mit möglichst wenig Aufwand "AddOns" (z.B. eine fliegende Einheit) hinzufügen kann (ist ja schließlich der Sinn der Dynamik).

Bin euch wirklich dankbar für eure Hilfe :)
 

Xeonkryptos

Bekanntes Mitglied
Außer ich gehe über diesen Weg: ((Krieger)einheit). (Wie nennt man diese Vorgehensweise?)

Das nennt sich "Casting" und ist nicht immer die beste Lösung, da der Compiler voraussetzt, dass die Information wirklich castbar ist, denn ansonsten würdest du eine Exception bekommen und dein Programm abstürzen. Durch die hier verwendete Polymorphie ist das in diesem Fall möglich, aber wie du schon festgestellt hast, sehr festgefahren und eine andere Möglichkeit nicht möglich. Zumindest keine, die mir jetzt einfällt und schön ist. =)
 

Illuvatar

Top Contributor
Vielleicht mal ein Denkanstoß in die Richtung die mir am sinnvollsten erscheint:
Du könntest eine neue Klasse Resource einführen. Die würde dann insbesondere die Methode getName besitzen, außerdem die maximal verfügbare Menge für die jeweilige Einheit und vermutlich den momentanen Stand.
Die Klasse Einheit könntest du dann so allgemein halten, dass eine Einheit mehrere Resourcen besitzt, und somit nicht nur Mana, Kraft und Pfeile sondern sogar auch Leben als Resource darstellen. Außerdem wäre es dann simpel, z.B. noch einen "Barbar" einzufügen, der Leben, Stärke und außerdem noch Alkohol benötigt ;)
Und das wichtige: Im Code für die Anzeige muss nicht mehr gecastet werden.

Edit: So mein ich das
Java:
public enum ResourceType {
  LIFE("Leben"),
  MANA("Mana"),
  POWER("Kraft"),
  ARROWS("Pfeile");
  
  private final String name;
  
  private ResourceType(String name) {
    this.name = name;
  }
  
  public String getName() {
    return name;
  }
}

public class Resource {
  private final ResourceType type;
  private final int maxValue;
  private int currentValue;
  
  public Resource(ResourceType type, int maxValue) {
    this.type = type;
    this.maxValue = maxValue;
    this.currentValue = maxValue;
  }
  
  // Diverse getter/setter Methoden
}
 
Zuletzt bearbeitet:
J

jd546

Gast
Es gibt durchaus Möglichkeiten, sowas objektorientiert zu lösen:

1. Du abstrahierst die Eigenschaften deiner Einheiten: Mana, Pfeile, usw. sind ja alle irgendwelche "Munition", ein Schild ist ein "Verteidigungsutensil" etc.

2. Auch Verhalten lässt sich abstrahieren und kapseln. Bestimmtes Grundverhalten ist ja auch allen Einheiten gemein: andere Einheiten angreifen / verletzt werden, geheilt werden, ...
Und mit dem Strategy Pattern kannst du das Verhalten auch bequem in eigene Klassen auslagern und deine Einheiten sogar zur Laufzeit mit neuem Verhalten versorgen.
 

Marco13

Top Contributor
((Krieger)einheit). (Wie nennt man diese Vorgehensweise?) Aber hier ist das Problem, dass mein Projekt dadurch an der Stelle sehr festgefahren wird.

"Casten". Ja, und es ist wirklich sehr spezifisch. Vielleicht würde es helfen, wenn du genauer sagen würdest, WANN du WO und WARUM den Unterschied zwischen den Einheiten kennen musst.
 

bluerob

Mitglied
Die Idee mit der extra Klasse Resource hört sich interessant an, aber ich verstehe diesen Part nicht:

Java:
public enum ResourceType {
  LIFE("Leben"),
  MANA("Mana"),
  POWER("Kraft"),
  ARROWS("Pfeile");

Aber auch das Public Patern hört sich gut an. Hab vorhin mal bisschen etwas dazu gelesen, habe ich das richtig verstanden?
Auf mein Projekt übertragen würde das bedeuten, dass ich eine Klasse Einheit habe.
Dieser würde ich abstrakte Methoden wie z.B.:
  • z.B. getMunition() geben, und je nach Angabe, z.B. Magier, würde diese Methode auf meine Klasse Magier zugreifen und dort über getMana() die "Munition" abrufen?
  • ich schreibe eine Methode angriff() und wieder je nach Angabe, greift die Methode z.B. auf die Klasse Bogenschütze zu und benutzt dort eine Methode, um einen Pfeil zu schießen?

Vielleicht würde es helfen, wenn du genauer sagen würdest, WANN du WO und WARUM den Unterschied zwischen den Einheiten kennen musst.

Habe es mir so überlegt, dass in meinen Subklassen (Magier,etc.) die spezifischen Skills und Attribute verankert sind. Wenn jetzt meine Staffel ausgelesen wurde und im Simulator auf dem Schlachtfeld steht, muss man natürlich wissen, welche Einheiten auf dem Feld stehen, um dementsprechend spezifische Attribute, wie z.B. Mana, zu ändern oder um die Einheiten Skills benutzen zu lassen, die wirklich nur diese Sorte von Einheit kann. Deswegen muss ich die Staffel so auslesen, dass ich genau weiß, welche Objekte der Liste hinzugefügt wurden.
Hoffe das beantwortet deine Frage.
 

Marco13

Top Contributor
Habe es mir so überlegt, dass in meinen Subklassen (Magier,etc.) die spezifischen Skills und Attribute verankert sind. Wenn jetzt meine Staffel ausgelesen wurde und im Simulator auf dem Schlachtfeld steht, muss man natürlich wissen, welche Einheiten auf dem Feld stehen, um dementsprechend spezifische Attribute, wie z.B. Mana, zu ändern oder um die Einheiten Skills benutzen zu lassen, die wirklich nur diese Sorte von Einheit kann. Deswegen muss ich die Staffel so auslesen, dass ich genau weiß, welche Objekte der Liste hinzugefügt wurden.
Hoffe das beantwortet deine Frage.

Hmnaja, nicht direkt: So viel war eigentlich vorher schon fast klar :D Etwas spezifischer:
Attribute, wie z.B. Mana, zu ändern
Wann passiert das, wodurch wird es ausgelöst, und wie läuft es ab?

Skills benutzen zu lassen, die wirklich nur diese Sorte von Einheit kann
Auch da: Was ist der Anlass dafür, dass so ein spezifischer Skill benutzt wird?

Etwas vereinfacht und "absolut" gesprochen: Wenn die Einheiten in einer einzigen List<Einheit> gespeichert werden sollen, dann MUSS man auch dafür sorgen, dass alle Einheiten gleich behandelt werden können. Andernfalls kommt man um (i.a. häßliche und schlecht erweiterbare) Typabfragen nicht drumrum. Man muss dann ggf. abwägen, ob diese Vereinheitlichung vielleicht häßlicher wäre, als die Typabfragen, aber das steht und fällt mit der Frage, wie der geplante Ablauf dieses Programms ist. Wie schon angedeutet können Typabfragen oft durch weiter gehende Abstraktion vermieden werden, aber die Praktikabilität dessen hat auch Grenzen.

Oder mal ganz konkret: Man hat eine Staffel, die nur Krieger und EINEN Magier enthält. Die Krieger haben eine spezielle Methode "kämpfe()", und der Magier hat eine spezielle Methode "wendeZauberAn()". Vermutlich bezieht sich darauf auch der erste Punkt: Wenn man die Methode "wendeZauberAn()" aufgerufen hat, muss man danach wohl sowas machen wie "reduziereVerfügbaresManaUm(x)"?

Wer soll entscheiden, welche der Methoden aufgerufen wird? (Bisher hattest du diese spezifische Behandlung nur in der Klasse "Staffel" angedeutet...)

Im einfachsten Fall könnten die beiden Methoden ("Krieger#kämpfe()" und "Magier#wendeZauberAn()") ja verallgemeinert werden, wie jd546 es schon angedeutet hat: In beiden Fällen ist das eine Form eines "Angriffs"- Man könnte also in das interface "Einheit" eine solche Methode einbauen, und die dann passend implementieren:
Java:
interface Einheit { void angriff(); }

class Krieger implements Einheit {
    public void angriff() {
    ....
    }
}

class Magier implements Einheit {
    private int mana = 123;

    public void angriff() { 
        // Alles spezielle steckt hier drin 
        if (mana > 0) {
            führeZaberAus();
            reduziereManaUm(10); // Auch das hier!
        } else {
            schlageMitDemZauberstab();
        }
    }
}

Dann müßtest du dir aber noch genauer überlegen, wie die "Angriffe" der einzelnen Einheiten im Detail ablaufen und aussehen sollten. Wer entscheidet wo, welche Einheit der gegnerischen Staffel angegriffen wird? Welche Besonderheiten gibt es beim "angegriffen werden"? Ein Beispiel: Man könnte sagen, dass ein Angriff durch eine Methode durchgeführt wird wie
Java:
interface Einheit { 
    void kassiereAngriff(int möglicherSchaden); 
}

Diese Methode kann dann wieder unterschiedlich implementiert sein, z.B.
Java:
class Krieger implements Einheit {

    private boolean hatSchild;
    private int lebenskraft;

    public void kassiereAngriff(int möglicherSchaden) {
        if (hatSchild && möglicherSchaden < 10) {
            System.out.println("Angriff mit Schild abgewehrt");
        } else {
            lebenskraft -= möglicherSchaden;
            if (lebenskraft < 0) sterbe();
        }
    }
}
oder so. Aber vielleicht kommen da noch mehr spezifische Dinge dazu. Vielleicht kann sich ein Magier gut gegen einen anderen Magier verteidigen, und bekommt nur Schaden, wenn sein Mana geringer ist, als das des anderen oder so. Das sind alles Dinge, die man bei einer allgemeingültigen Beschreibung irgendwie "wegabstrahieren" müßte. Und im Idealfall sollte man sich (möglichst viel oder zumindest) einiges davon schon überlegen, bevor man mit dem "Runterimplementieren" anfängt...
 

bluerob

Mitglied
Oder mal ganz konkret: Man hat eine Staffel, die nur Krieger und EINEN Magier enthält. Die Krieger haben eine spezielle Methode "kämpfe()", und der Magier hat eine spezielle Methode "wendeZauberAn()". Vermutlich bezieht sich darauf auch der erste Punkt: Wenn man die Methode "wendeZauberAn()" aufgerufen hat, muss man danach wohl sowas machen wie "reduziereVerfügbaresManaUm(x)"?

Wer soll entscheiden, welche der Methoden aufgerufen wird? (Bisher hattest du diese spezifische Behandlung nur in der Klasse "Staffel" angedeutet...)


Dann müßtest du dir aber noch genauer überlegen, wie die "Angriffe" der einzelnen Einheiten im Detail ablaufen und aussehen sollten. Wer entscheidet wo, welche Einheit der gegnerischen Staffel angegriffen wird? Welche Besonderheiten gibt es beim "angegriffen werden"?

Ich möchte noch eine extra Klasse KI anlegen, welche meinen Einheiten dann Situationsabhängig Befehle gibt.

Hab mir jetzt nochmal überall die Vorschläge rausgeschrieben und werde mir erstmal etwas darüber durchlesen.

Edit:

Kann mir mal jemand den Sinn von einem Interface erklären?
Habe mir jetzt dazu etwas durchgelesen und mir kommt es so vor, als wäre es nur eine Art Rahmen.
Aber was bringt das, wenn ich trotzdem die Methoden jedes mal schreiben muss? Dann kann ich die doch auch unabhängig vom Interface schreiben oder?

Edit:

Habe mich jetzt mal ein bisschen ans Strategy Pattern gemacht, damit klappt eigentlich alles wunderbar. Werde halt schauen müssen, wie weit ich mit dem Abstrahieren komme.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
L Generische ArrayList, CastProblem Java Basics - Anfänger-Themen 2
J array über generische arraylist Java Basics - Anfänger-Themen 7
I Generische Funktion Java Basics - Anfänger-Themen 3
B Generische Typen für dynamisches Formular Java Basics - Anfänger-Themen 3
A Generische Klassen/Interface Java Basics - Anfänger-Themen 1
H Generische Konstruktor Java Basics - Anfänger-Themen 12
Kirby.exe Generische Objekt Instanz erstellen Java Basics - Anfänger-Themen 14
D Generische Klasse Java Basics - Anfänger-Themen 6
H linkedlist generische klassen Java Basics - Anfänger-Themen 169
M Datentypen Generische Datentypen - Syntax Java Basics - Anfänger-Themen 25
O Generische Typen Java Basics - Anfänger-Themen 9
M Generische Klassen "FlaschenRegal" Java Basics - Anfänger-Themen 13
Queiser Datentypen 2 generische Datentypen für eine Schnittstelle Java Basics - Anfänger-Themen 1
M Generische Liste aus Comparable-Objekten Java Basics - Anfänger-Themen 6
J Sortierte generische Liste Java Basics - Anfänger-Themen 1
D statische generische Methoden Java Basics - Anfänger-Themen 3
S Wie muss ich die Generische Methode schreiben? Java Basics - Anfänger-Themen 6
M Methoden Generische Klasse - ändern einzelner Attributwerte Java Basics - Anfänger-Themen 2
S generische methode mit verschiedenen datentypen Java Basics - Anfänger-Themen 3
N Generische Schnittstellen Java Basics - Anfänger-Themen 2
B generische LinkedList nach Häufigkeit der Elemente füllen Java Basics - Anfänger-Themen 6
D Generische Typen Java Basics - Anfänger-Themen 20
S Erste Schritte Generische Klassen sind toll ....aber warum sollte ich das je benutzen? Java Basics - Anfänger-Themen 3
L Generische Liste Java Basics - Anfänger-Themen 4
B Generische Queue programmieren Java Basics - Anfänger-Themen 5
S Generische Methode soll Objekte als Parameter erlauben die bestimmtes Interface implementieren^ Java Basics - Anfänger-Themen 9
A Probleme mit MergeSort Generische Liste Java Basics - Anfänger-Themen 0
A Generische Methode Java Basics - Anfänger-Themen 4
H Collections List in List<SpecificType> als stat. generische Methode zurückgeben Java Basics - Anfänger-Themen 4
J Probleme mit static generische Klasse Java Basics - Anfänger-Themen 6
M Generische Liste Java Basics - Anfänger-Themen 4
B Generische Methode Java Basics - Anfänger-Themen 2
B Generische Klasse Java Basics - Anfänger-Themen 7
B Generische Methoden Java Basics - Anfänger-Themen 8
F Collections Generische Klasse/Methoden Java Basics - Anfänger-Themen 19
L Generische Warteschlange Java Basics - Anfänger-Themen 8
A Generische Datentypen Java Basics - Anfänger-Themen 8
L Generische Containerklasse Java Basics - Anfänger-Themen 9
V Methoden Umwandlung in generische Methode Java Basics - Anfänger-Themen 8
A Generische Collections und Vererbung Java Basics - Anfänger-Themen 2
S Generische HashMap Java Basics - Anfänger-Themen 2
M Klassen Generische Klassen, Personen und Gruppen Java Basics - Anfänger-Themen 6
W generische Module Java Basics - Anfänger-Themen 2
S Generics und "generische Feldzuweisungen" Java Basics - Anfänger-Themen 5
C unterschied generische typen und supertypen als methodenparameter Java Basics - Anfänger-Themen 3
D Datentypen Generische Collections und Warnings Java Basics - Anfänger-Themen 8
F Generische Methoden Problem Java Basics - Anfänger-Themen 5
E Generische Arrays durch Typecast mit Object-Array Java Basics - Anfänger-Themen 11
K Generische Klasse mit innerer Klasse | Problem mit Array Java Basics - Anfänger-Themen 6
B Was passiert, wenn eine konkrete Klasse von generische Klasse erbt? Java Basics - Anfänger-Themen 14
B Generische Vererbung was ist der Unterschied? Java Basics - Anfänger-Themen 4
W Generische Klassen Java Basics - Anfänger-Themen 3
W Generische Klassen und Casting Java Basics - Anfänger-Themen 6
F Generische Typen auch für statische Methoden? Java Basics - Anfänger-Themen 13
B instanceof Prüfung für generische Typen Java Basics - Anfänger-Themen 5
N 2 dimensionale generische Arrays Java Basics - Anfänger-Themen 9
H Statische generische Methode Java Basics - Anfänger-Themen 2
G Frage zum Ungang mit Generische Datentypen Java Basics - Anfänger-Themen 4
0x7F800000 generische arrays mal wieder )-; Java Basics - Anfänger-Themen 6
D generische methode <T> void . Java Basics - Anfänger-Themen 9
J Generische Methoden Java Basics - Anfänger-Themen 6
G Doppelt verkettete, generische Liste Java Basics - Anfänger-Themen 11
S Parameterübergabe: Generische Klasse Java Basics - Anfänger-Themen 4
S generische Felder Java Basics - Anfänger-Themen 2
P Generische Klasse Java Basics - Anfänger-Themen 8
C Generische Klassen, das erste Mal. Java Basics - Anfänger-Themen 8
F Generische Methode - was bringt der Wildcard Operator? Java Basics - Anfänger-Themen 7
F Generische Liste von generischen Objekten. Java Basics - Anfänger-Themen 3
H generische Methoden Java Basics - Anfänger-Themen 5
N generische HashMap und Iterator Java Basics - Anfänger-Themen 2
H generische Bausteine, heterogene Datenstrukturen Java Basics - Anfänger-Themen 2
J generische klassen neue Instanz Java Basics - Anfänger-Themen 5
H Generische Klassen. Java Basics - Anfänger-Themen 16
krgewb ArrayList allgemein halten Java Basics - Anfänger-Themen 6
M Ausgabe einer ArrayList ensteht nur als Hashcode, nicht als Objekt Java Basics - Anfänger-Themen 16
S Java: Wie sortiere ich eine ArrayList benutzerdefinierter Objekte nach einem bestimmten Attribut? Java Basics - Anfänger-Themen 2
J ArrayList in 2D-Array konvertieren. Java Basics - Anfänger-Themen 48
E Arrays in einer ArrayList miteinander vergleichen Java Basics - Anfänger-Themen 12
String in ArrayList umwandeln Java Basics - Anfänger-Themen 1
F Arraylist<String>Ein Wort pro Zeile Java Basics - Anfänger-Themen 6
J ArrayList vergleichen im spiel Mastermind Java Basics - Anfänger-Themen 2
Mugetsu35 ArrayList Update ohne Index Java Basics - Anfänger-Themen 6
W Objekte einer ArrayList in txt-datei schreiben mit Paths? Java Basics - Anfänger-Themen 2
Z Java ArrayList speichert falsche Daten ab bzw. gibt falsche Daten aus? Java Basics - Anfänger-Themen 42
W if-Abfrage bei ArrayList-Methodenaufrufen - Wie löse ich das? Java Basics - Anfänger-Themen 6
W ArrayList und toString Java Basics - Anfänger-Themen 17
volcanos Addition -> List<Integer> mit Arrays.asList() versus List<Integer>ArrayList<>() Java Basics - Anfänger-Themen 14
ArrayList mit unbekannter Menge an Arrays die Arrays vergleichen Java Basics - Anfänger-Themen 9
M 2d ArrayList durchgehen Java Basics - Anfänger-Themen 2
Blkckroll45 Arraylist Java Basics - Anfänger-Themen 6
H Interface Wieso "List<String> list = new ArrayList<>[…]" Java Basics - Anfänger-Themen 4
berserkerdq2 Geht collections.sort bei allen? Linkedhashset, ArrayList, HashSet etc. Java Basics - Anfänger-Themen 4
R Methoden Werte einer ArrayList als Parameter übergeben. Java Basics - Anfänger-Themen 4
L Dauerhaftes Speichern einer Eingabe bei einer ArrayList Java Basics - Anfänger-Themen 26
D Arraylist mit Komplexen Datentyp Java Basics - Anfänger-Themen 3
H Kompliziertes Sortieren einer ArrayList mit Objekten(Sortieren nach X und Y) Java Basics - Anfänger-Themen 11
T Permanentes speichern von Objekten in einer ArrayList Java Basics - Anfänger-Themen 6
volcanos List & ArrayList nach Familiennamen abfragen Java Basics - Anfänger-Themen 57
M static ArrayList in non-static Java Basics - Anfänger-Themen 12
berserkerdq2 Ich gebe eine ArrayList als List zurück per MEthode, wie kann ich nun aber die ArrayList speichern? Java Basics - Anfänger-Themen 46

Ähnliche Java Themen

Neue Themen


Oben