# Array mit verschiedenen Klassen



## nopro (2. Nov 2005)

hallo! 

ich möchte ein stragtegiespiel programmieren. 
darin will ich ein array Einheit[] e=new Einheit[einheitenAnzahl]; erstellen. 

aber Einheit soll nur die Superklasse der versch. einheitentypen sein. 
zb: Superklasse: Einheit   -   Subklassen: Panzer, Soldat; 
kann ich ein Array erstellen, in das ich Panzer UND Soldaten ablegen kann??

zur veranschaulichung, was ich meine: 
dann könnte man schreiben; 


```
if(e[x].getClass()==Soldat){
      e[x].laufNach(1,1);
}
if(e[x].getClass()==Panzer){
    e[x].fahrNach(1,1);
}
```

gibt es da eine eifache/gängige Lösung??


----------



## Bleiglanz (2. Nov 2005)

ja, nimm ein Array von Einheiten

nur die prüfung machst du dann mit instanceof


----------



## Sky (2. Nov 2005)

Soldat und Panzer könnten eine Methode "moveTo" haben anstatt "laufNach" und "fahrNach". Diese "moveTo"-Methode sollte abstract in Einheit deklariert sein.

Dann ist vollkommen egal, was für eine Einheit sich bewegen soll; das Objekt selbst (also Soldat oder Panzer) weiß, wie es eine Bewegung ausführen muss.


----------



## GagamehlO (2. Nov 2005)

oberklasse[] array = new oberklasse[n];
oberklasse[0] = unterklasse1;
oberklasse[1] = unterklasse2;
oberklasse[2] = unterklasse1;
oberklasse[3] = unterklasse2;
//etc.....

Schleife zum durchlaufen
{
if(oberklasse[n] instanceof unterklasse1) ...
...


}


Du bekommst mit getClass ein Object der Klasse Class, dies kannst du nicht so einfach vergleichen.
Du könntest mit der toString() Methode dir den Namen der Klasse ausgeben lassen und diesen dann überprüfen
aber mit instanceof ist es wohl doch leichter.
Alternativ kannst du der Klasse Soldat und Panzer ein "Null"-interface implementieren aus dessen Typ du ein Array machst.
So benötigst du keine Oberklasse


EDIT: Huch da waren wohl welche Schneller.


----------



## Mag1c (2. Nov 2005)

Obwohl das nicht gerade OO-konform wäre. Besser dann so:


```
public abstract class Einheit {
  public abstract void bewegeNach (int x, int y);
}

public class Panzer extends Einheit {
  public void bewegeNach (int x, int y) {
    fahrNach(x, y);
  }

  public void fahrNach (int x, int y) {
    ...
  }
}

public class Soldat extends Einheit {
  public void bewegeNach (int x, int y) {
    laufNach(x, y);
  }

  public void laufNach (int x, int y) {
    ...
  }
}
```

EDIT: zu langsam  :bae: 

Gruß
Mag1c


----------



## Sky (2. Nov 2005)

Mag1c hat gesagt.:
			
		

> Obwohl das nicht gerade OO-konform wäre. Besser dann so:
> 
> 
> ```
> ...


Besser noch: Die laufNach bzw. fahrNach private zu machen (bzw. ganz darauf verzichten). Zwei Methoden, die das gleiche machen, da ist m.E. eine zuviel ;-) Also bei größeren Programmen kann das irgendwann zu Problem führen.


----------



## nopro (2. Nov 2005)

das ging ja schnell   danke! 
jetzt weiss ich auch, was ne abstract class ist...

aber ich hab noch ein problem: 
ich will, dass die Subclasses auch verschiedene Parameter haben. 
hier z.B. Panzer.höhe,breite Soldat.d (Durchmesser)


```
package twentyonedays;

public class Test {
	
	Einheit[] einheit=new Einheit[2];
	
	public static void main(){
		Test t=new Test();
		t.testit();
	}
	
	public Test() {
		super();
	}
	
	void testit(){
		einheit[0]=new Soldat();
		einheit[1]=new Panzer();
		System.out.println(einheit[0].d);
	}
	
	class Einheit{
		int x,y;
		Einheit(){
			super();
		}
	}
	
	class Soldat extends Einheit{
		int d;//durchmesser;
		Soldat(){
			super();
		}
	}

	class Panzer extends Einheit{
		int höhe,breite;
		Panzer(){
			super();
		}
	}
}
```

in meinem beispiel klappt das nicht. 
gibt es dafür auch eine lösung??


----------



## nopro (2. Nov 2005)

PS: der Fehler komt in Zeile 19 
"d can not be resolved or is not a field"


----------



## Sky (2. Nov 2005)

Anonymous hat gesagt.:
			
		

> PS: der Fehler komt in Zeile 19
> "d can not be resolved or is not a field"


Weil "Einheit" kein 'd' hat; das haben nur Soldaten!


----------



## nopro (2. Nov 2005)

das is mir schon klar. 
aber ich WILL ja, dass einheit[0] ein 'd' hat.


----------



## Sky (2. Nov 2005)

pack doch breite und höhe in einheit. 
wenn es sich um einen durchmesser handelt, so ist breite = höhe


----------



## nopro (2. Nov 2005)

das spiel soll ja noch umfangreicher werden. 
viele verschiedene arten von 'Einheit' werden dann viele verschiedene einheiten haben. 

ich hab das jetzt so gelöst: 
neben 'Einheit' gibt es noch eine Klasse 'EinheitInstanz' 


```
package derSpieler;

import dieEinheiten.*;
import dieSteuerung.*;

public class EinheitInstanz {
	
	int typ;
	Gewehrmann gewehrmann;
	Panzer panzer;
	
	public EinheitInstanz(int typ) {
		super();
		this.typ=typ;
		if(typ==1){
			gewehrmann=new Gewehrmann();
		}
		if(typ==2){
			panzer=new Panzer();
		}
	}
	
	public Menü getMenü(){
		if(typ==1){
			return Gewehrmann.menü;
		}
		if(typ==2){
			return Fahrzeug.menü;
		}
		return new Menü();
	}
}
```

(jede Subclass kriegt ein static Menü, dass gezeigt wird, wenn eine einheit angeklickt ist)

ist zwar umständlich das für jede neue Subclass von 'Einheit' umzuprogrammieren, 
aber praktisch das von aussen zu benutzen...


----------



## Bleiglanz (2. Nov 2005)

das ist schlecht gelöst, was du meinst ist eine EinheitenFactory

```
public class EinheitFactory{

   public static Einheit createEinheit(int typ) {
       Einheit result = null;
       switch(typ){
           case 0: result = new Fahrzeug(); break;
           case 1: result = new Panzer(); break;
           ....
           default: throw new IllegalArgumentException(); 
       }
       return new result;
   }
}
```
bei deiner Methode nutzt du die Vorteile von OO überhaupt nicht


----------



## nopro (2. Nov 2005)

da kommen doch wieder nur 'Einheit'en raus, oder?


----------



## Sky (2. Nov 2005)

Anonymous hat gesagt.:
			
		

> da kommen doch wieder nur 'Einheit'en raus, oder?


Aber das sollte auch Sinn und Zweck sein im OO-Ansatz.
Wenn du zig verschiedene Dinge in ein Array packst, und dann jedesmal fragst: "Was bin ich für ein Objekt" und "Was muss ich denn jetzt machen" führt das zu zig if-else-Anweisungen, wo es gar nicht nötig wäre.
Überleg Dir, welche Eigenschaften eine Einheit haben muss und welche Methoden eine Einheit braucht.

Zu deinem Code: eine als 'abstract' definierte Methode getMenu gibt das jeweilige Menü der Einheit zurück; egal ob Panzer oder Soldat.


----------



## Mag1c (3. Nov 2005)

Moin,

also da kann ich meinen Vorschreibern nur beipflichten. Deine EinheitInstanz-Klasse ist eigentlich eine EinheitFactory (siehe Factory-Pattern). Wenn du für jede Einheit ein Menü haben willst, mach das genauso wie oben die Methode bewegeNach(...). Also abstrakte Methode getMenu() in der Klasse Einheit und in den abgeleiteten Klassen dann die Implementierung für den jeweiligen Typ.

Gruß
Mag1c


----------

