Klassen Ein nicht existierendes Objekt in Parametern übergeben

Fesker

Mitglied
Hallo ihr Lieben...
Ich bin dabei, eine art Baureihenfolge zu programmieren.
In einer Tabelle soll ein zu bauendes Raumschiff dargestellt werden. (Hauptsächlich der Name)
Daneben der Baubeginn und die Zeit der Fertigstellung.
Die Tabelle funktioniert soweit, nur haperts irgendwie trotzdem an einer praktikablen Umsetzung.

Wenn ich auf einen Button klicke wird die funktion
Java:
public void BuildShip(String ship, Planet p){		
		 p.shipBuildListModel.addBuildOrder(ship);			
	}
aufgerufen.
Der Planet Existiert ja schon, nur das Schiff nicht, soll ja auch vorerst noch gar nicht. (Oder doch?)

Im TableModel sieht die benannte Funktion so aus:
Java:
public void addBuildOrder(String ship){    	
    	DateTime currentTime = new DateTime();       // JODA-Time	
    	List<String> newOrder = new ArrayList<>();    	
    	    	
    	newOrder.add(ship); // evtl. ship.getName() o.ä.
    	newOrder.add(currentTime.toString("dd.MM.yyyy_HH:mm:ss"));
    	newOrder.add("test"); //<-- Was ist zu tun?
    	rows.add(newOrder);
    	fireTableRowsInserted(rows.size()-1,rows.size()+1);
    }

Wie gesagt, sind erst mal nur Strings.
Bei der Zeile "test" soll dann eigentlich das Datum der Fertigstellung hin - also die Zeit des Baubeginns PLUS die Zeit, die jeder Schiffstyp individuell benötigt.

Dazu habe ich eine Klasse "Ship" und eine Unterklasse namens "Speeder" angelegt.
Siehe hier:
Java:
public class Ship {
	int minHP;
	int minSP;
	int maxHP;
	int maxSP;
	int prize;      // SofortkaufKosten
	int buildTime; // in Sekunden	
	float speed;	
	int[][] position;
	String name;
	
	public int getBuildTime(){ return buildTime; }
	public String getName()  { return name;}
}
Java:
public class Speeder extends Ship {
		
	Speeder(){ // ID = Ort wo es gebaut wurde und wo es dann später eingetragen werden soll
		this.buildTime = 1;
	}
}

Meine Frage ist nun:
Wie kann ich per Buttonklick sagen, dass ein nicht existierendes Speederobjekt an mein tableModel weitergegeben wird?
Später soll ja über ein Dropdown o.ä. solche Vorgänge realisiert werden.
Oder sollte ich das einfach über eine switch-schleife machen, und dann je nach Case irgendwie ein Platzhalterobjekt erzeugen? Wie macht man das in richtigen Spielen?
Oder gibts da irgendwelche (cast)-möglichkeiten um an die individuellen Bauzeiten zuzugreifen?

Grüße!
 
Zuletzt bearbeitet:
Wozu diese Speeder Klasse gut ist erschließt sich mir leider nicht.

Wozu denn der Platzhalter? Soll nun etwas gebaut werden oder nicht?

Ich weiß nicht, wie das ein Profi machen würde aber ich würde es so machen:
Es gibt eine Hauptklasse. Diese ruft in einer weiteren Klasse die Logik auf. Diese Logikklasse verwaltet die einzelnen Galaxien, Sternenhaufen, Sonnensysteme oder auch nur Planeten. Eben den Größten dieser vier Dinge. Diese beherbergen dann den nächstkleineren und immer so weiter. Die Planeten verwalten ihre Werften. Und die Werften verwalten ihre Schiffe und übergeben diese bei Fertigstellung an die Planeten, die sich um die weitere Verwaltung kümmern.
 
Insgesamt finde ich das alles ein wenig durcheinander und wirklich klar ist mir das, was eigentlich genau fragen willst nicht, aber falls ich dich einigermaßen richtig verstehe, dann würde die Variablen wie die Bauzeit als
Code:
static final
deklarieren. Dann kannst du unabhängig von einer konkreten Schiffsinstanz mittels
Code:
Ship.buildTime
bzw
Code:
Speeder.buildTime
auf diese Werte zugreifen.
Möglicherweise ist es auch sinnvoll die verschiedenen Schiffstypen samt ihrer Kerndaten in einem enum zu realisieren. Die eigentliche Schiffsinstanz merkt sich dann ihren Schiffstyp und wirklich ganz spezifische Daten, wie z.B. das Datum, an dem es erstellt wurde, den Namen, den aktuellen Schaden und was weiß ich nicht alles...
 
Da dieser Thread immer länger wird, habe ich ihn mal genauer gelesen und geben meinen Senf dazu..

Überschrieben ist der Beitrag mit
Ein nicht existierendes Objekt in Parametern übergeben
Dies geht (natürlich) nicht.

In einer Tabelle soll ein zu bauendes Raumschiff dargestellt werden
Es gibt also Schiffe, die bereits fertig sind und zu-bauende-Schiffe, nennen wir diese SchiffBauanleitung.

In deiner Tabelle zeigst du anscheinend beide Exemplare an. Natürlich sind beide Arten von Schiffen existierende Objekte. Ersteres kann sogar bereits fliegen und an Missionen teilnehmen, während das Letztere noch warten muss bis es fertig ist. Sieht so aus als ob es verschiedene SchiffBauanleitungen gibt, nämlich für einen Kreuzer oder ein Schlachtschiff, oder.. Kreuzer braucht "nur" 3 Wochen zur Fertigstellung, Schlachtschiff dagegen zwei Jahre.

Die andere Diskussion verstehe ich nicht.
 
Ich habe die ganze Organisation des Programmes nicht verstanden und wollte dem Threadstarter deshalb einen Hinweis geben, wie man das ganze organisieren könnte.

Die Raumschiffe hätten entweder eine Variable, die ihren Status als im Bau befindlich kennzeichnet oder es gibt extra "im Bau Raumschiffe".
 
Die Raumschiffe hätten entweder eine Variable, die ihren Status als im Bau befindlich kennzeichnet
Ich habe dich genau verstanden😉
Diese Modellierung ist meiner Meinung nach zu sehr verwoben mit dem wofür der TO dieses alles braucht. Wenn man diesem Vorschlag folgen würde, wäre überall Code involviert der den Status prüfen muss. Beispielsweise ein Raumschiff ist beschädigt und muss zur Reparatur. Ist das wieder ein Schiffsbau oder sagen wir, es ist im Status "Reparatur"? Beides kann Sinn machen.

oder es gibt extra "im Bau Raumschiffe".
Da ich auf derartige Diskussionen nicht eingehen wollte, habe ich das Grundproblem angegangen und das ist eindeutig ein "Raumschiff in Bau". Da ist der Status im Typ "versteckt" automatisch drin. Wenn man diesem Vorschlag folgen würde, wäre ein Raumschiff-in-Reparatur ein weiterer Typ Raumschiff.
 
Sollte man so etwas dann nicht mit einem Sttus-Interface lösen?

RaumschiffImBau extends Raumschiff implements imBau {}
RaumschiffReparatur extends Raumschiff implements inReparatur {}
 
Zuletzt bearbeitet:
if (new RaumschiffImBau instanceof imBau) { ...}

Wenn du ein analogium machst zu allesOk hast du eine einfache Prüfung, ob das Raumschiff die gewünschte Aktion ausführen darf.
 
Ich schließe mich der Idee von stg an und kenne das auch so aus der Praxis. Man möchte normalerweise nicht für jeden Objekttyp im Spiel eine eigene Klasse haben, weil Erweiterungen des Spiels dann immer Änderungen am Code benötigen. Außerdem wird man sehr viel mehrfach verwendeten Code haben, wenn sich verschiedene Raumschiffstypen kaum unterscheiden. Programmierer gehören zu den teuersten Mitgliedern im Team, deshalb sollten Anpassungen und Erweiterungen in kommerziellen Projekten möglichst auch von anderen Leuten erledigt werden können.

Bei einem großen und vollendeten MMORPG-Projekt, an dem ich mal mitgearbeitet habe, gab es nur ein paar Basisklassen: Item, Mobile und ein paar weitere. Das Verhalten des Items und Mobiles (sofern es NPCs waren) wurde über externe Dateien (im einfachsten Fall Textdateien mit Attribute-Wert-Paaren, im besten Fall Scripte in irgendeiner Scriptsprache) festgelegt. Auf diese Weise konnten auch die Nicht-Programmierer des Projekts neue Gegenstände hinzufügen, einfach indem sie dafür eine Textdatei mit der Beschreibung und den Attributen anlegen. Die kann der Server dann sogar neu einlesen, während das Spiel noch aktiv ist, d.h. neue Gegenstände sind ohne Neustart möglich.

Wenn man das vernünftig umsetzt, ist das auch nicht gegen die Lehre der Objektorientierung.
 
Zuletzt bearbeitet:
if (new RaumschiffImBau instanceof imBau) { ...}
Das ist weder eine Antwort auf die Frage, noch korrekter Java-Code, noch ergibt es inhaltlich einen Sinn (RaumschiffImBau-Instanzen sind immer Instanzen von ImBau ...).

Also noch mal konkret gefragt:
  • Wie handhabst du bei deinem Ansatz die Zustandsübergänge eines Raumschiffs zur Laufzeit? An der Klasse und den Interfaces bereits fertig instanziierter Objekte zu drehen kannst du ja vergessen. Oder wolltest du einfach nur Adapter für die Raumschiffe zur Verfügung stellen?
  • Welchen Sinn haben die Interfaces ImBau und InReparatur überhaupt, und was sind "Status-Interfaces"? Es widerspricht ziemlich dem Sinn von Interfaces, das (Nicht-)Implementieren eines Interfaces dafür zu misshandeln, den Zustand einer Objekt-Instanz zu implementieren, da es genau dafür Objekt-Attribute gibt und vorhandenen Instanzen nicht zur Laufzeit irgendwelche Interfaces hinzugefügt oder weggenommen werden können. Es ist mir auch nicht bekannt, dass dieses schräge Vorgehen schon mal irgendwo praktiziert oder propagiert wurde.
 
Zuletzt bearbeitet von einem Moderator:
Ich behaupte ja nicht das mein Vorschlag auf lange Sicht ein guter Ansatz ist, aber...
Um so wichtiger ist es für alle Dinge jUnit-Tests zu haben, um ohne Probleme refactoren zu können.

Hier mein erster Test:Baue ein Raumschiff fertig und fliege damit zum Mond.

Java:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class TestSimple {

	@Test
	public void test() {
		TestSimple testSimple = new TestSimple();
		Raumschiff baueSchiff = testSimple.erstelleRaumschiffUndStelleFertig();
		assertNotNull(baueSchiff);
		assertTrue(baueSchiff instanceof MissionRraumschiff);
		baueSchiff.fliegezumMond();
		assertEquals("Ziel nicht Mond", "Mond", baueSchiff.getZielOrt());
	}

	private Raumschiff erstelleRaumschiffUndStelleFertig() {
		Raumschiff baueSchiff = new SchiffBauanleitung();
		if (baueSchiff instanceof SchiffBauanleitung) {
			SchiffBauanleitung zuBauendesSchiff = (SchiffBauanleitung) baueSchiff;
			baueSchiff = zuBauendesSchiff.stelleFertig();
			return baueSchiff;
		}
		return null;
	}

	class Raumschiff {
		private String zielOrt;

		public void fliegezumMond() {
			zielOrt = "Mond";
		}

		public String getZielOrt() {
			return zielOrt;
		}

		public void setZielOrt(String zielOrt) {
			this.zielOrt = zielOrt;
		}

	}

	class MissionRraumschiff extends Raumschiff {

	}

	class SchiffBauanleitung extends Raumschiff {

		public Raumschiff stelleFertig() {
			Raumschiff raumschiff = new MissionRraumschiff();
			return raumschiff;
		}

	}

}
 
Ich vereinfache mal:
Java:
private Raumschiff erstelleRaumschiffUndStelleFertig() {
    Raumschiff baueSchiff = new SchiffBauanleitung();
    if (baueSchiff instanceof SchiffBauanleitung) {
        SchiffBauanleitung zuBauendesSchiff = (SchiffBauanleitung) baueSchiff;
        baueSchiff = zuBauendesSchiff.stelleFertig();
        return baueSchiff;
    }
    return null;
}
Da baueSchiff instanceof SchiffBauanleitung immer wahr ist, kannst du auch gleich schreiben:
Java:
private Raumschiff erstelleRaumschiffUndStelleFertig() {
    return new SchiffBauanleitung().stelleFertig();
}
Wenn du dann noch die Implementierung von SchiffBauanleitung.stelleFertig einsetzt kommst du zu:
Java:
private Raumschiff erstelleRaumschiffUndStelleFertig() {
    return new MissionRraumschiff();
}

Was dann natürlich die Fragen aufwirft:
- welchen Sinn die Klasse SchiffBauanleitung in deinem Entwurf überhaupt hat
- ob hier überhaupt eine Behandlung der verschiedenen Lebenszyklen eines Raumschiffs stattfindet. Ich kann sie nirgendwo entdecken.
 
Zuletzt bearbeitet von einem Moderator:
Da baueSchiff instanceof SchiffBauanleitung immer wahr ist, kannst du auch gleich schreiben
Ja, im Test ist das (natürlich) immer wahr, aber...

Im richtigen Programm ist das anders, denn da hat der TO mit allgemeinen Raumschiffen zu tun.

Einige von denen können Raumschiffe-im-Bau (also SchiffBauanleitung) sein, andere können Raumschiffe-in-Mission (also MissionsRaumschiff) sein.

Was dann natürlich die Fragen aufwirft:
- welchen Sinn die Klasse SchiffBauanleitung in deinem Entwurf überhaupt hat
- ob hier überhaupt eine Behandlung der verschiedenen Lebenszyklen eines Raumschiffs stattfindet. Ich kann sie nirgendwo entdecken.
Gleiches Argument: Der Test deckt nur einen sehr kleinen Teil ab. Aber es sollte leicht möglich sein diese andere Dinge einzubauen und zu testen.

Orginal wollte der TO
Ich bin dabei, eine art Baureihenfolge zu programmieren.
In einer Tabelle soll ein zu bauendes Raumschiff dargestellt werden
Ich habe EINE MÖGLICHKEIT aufgezeigt wie dies mit verschiedenen Typen vom Raumschiffen umgesetzt werden kann.
 
Das ist weder eine Antwort auf die Frage, noch korrekter Java-Code, noch ergibt es inhaltlich einen Sinn (RaumschiffImBau-Instanzen sind immer Instanzen von ImBau ...).
Das war ein Beispiel, da kann ja auch RaumschiffImEinsatz kommen...
Also noch mal konkret gefragt:
  • Wie handhabst du bei deinem Ansatz die Zustandsübergänge eines Raumschiffs zur Laufzeit? An der Klasse und den Interfaces bereits fertig instanziierter Objekte zu drehen kannst du ja vergessen. Oder wolltest du einfach nur Adapter für die Raumschiffe zur Verfügung stellen?


  • Das ist ein Manko und dessen bin ich mir bewusst. Du musst zwingend die alte Instanz löschen und eine neue erstellen.

    • Welchen Sinn haben die Interfaces ImBau und InReparatur überhaupt, und was sind "Status-Interfaces"? Es widerspricht ziemlich dem Sinn von Interfaces, das (Nicht-)Implementieren eines Interfaces dafür zu misshandeln, den Zustand einer Objekt-Instanz zu implementieren, da es genau dafür Objekt-Attribute gibt und vorhandenen Instanzen nicht zur Laufzeit irgendwelche Interfaces hinzugefügt oder weggenommen werden können. Es ist mir auch nicht bekannt, dass dieses schräge Vorgehen schon mal irgendwo praktiziert oder propagiert wurde.

    Jein. Im Prinzip macht das Interface Serializable etwas ähnliches... Ich sage nicht, dass mein Vorgehen ideal ist. Es wäre jedoch sicherlich auch ein interessanter Weg...
 
Zuletzt bearbeitet:
Hey ihr Lieben,
hätte nicht gedacht, dass sich hier während meines Urlaubs doch so eine Diskussion findet.

Ja, das was stg anfangs geschrieben hatte, trifft's genau.
Ich kann von dem Tablemodel ja irgendwie nicht wirklich auf diese Bauzeiten zugreifen, da das Objekt nicht existiert.
Bin doch auch ein blutiger Anfänger und versuche mittels Learning by doing das O-Game Spielprinzip nachzubasteln.

Wie ist das mit den ENUMs gemeint?
Warum würde mein Objekt ohne ENUM seine Bauzeit nicht individuell speichern können, wenn ich doch "this." benutze?

Grüße!
 
In den ENUMS würde, so denke ich mir das, der aktuelle Status des Raumschiffes gespeichert. Also imBau, aufMission, zurVerfügung usw.

Die Bauzeit würde in einem primitiven Datentyp gespeichert. Da ENUMS zu verwenden würde den Ramen mehrfach sprengen. 😀
 

Zurück
Oben