OOP Wie benutze ich die Main Funktion richtig?

Baboon

Mitglied
Hallo,

ich sehe häufig Programme wie folgt strukturiert sind, dass es eine "Hauptklasse" gibt in der alle anderen Klasse initialisiert werden. Die Main-Funktion befindet sich dann in der Datei mit der "Hauptklasse" und initialisiert diese Klasse.

Zum beispiel habe ich Snake programmiert. Da habe ich eine Klasse die heißt bei mir einfach "Snake". Dazu noch eine die heißt Hero und Point. Hero ist die Schlange und Point ist dieser Punkt den man fressen muss.

Die main funktion macht einfach:
Java:
public static void main(String[] args){
       new Snake();
}

Der Snake konstruktor macht dann das:
Java:
public Snake(){
        Hero hero = new Hero(param);
        Point point = new Point(param);
        ...
}

So, meine Frage ist. Ist das sinnvoll? Mein Professor hat kurz mal gesagt, das sowas nicht gut ist.
Warum und wie es richtig ist hat er nicht gesagt. Ich hoffe es ist deutlich geworden was ich meine.

LG und danke schonmal
 
Zuletzt bearbeitet von einem Moderator:
Moin,

nun ja, was willst Du denn mit den beiden neuen Objekten machen ??

Einige Hinweise:
  1. So erzeugst Du zwei lokale Objekte, die außerhalb von Snake nicht gültig sind!
  2. alle Aktionen nur innerhalb des Konstruktors auszuführen, würde jeglichem OOP-Gedanken widersprechen!
  3. Dein Parameter 'param' fällt hier ziemlich vom Himmel ..... 😉
Hier noch ein paar nette Links zur main-Methode:
http://www.cs.princeton.edu/courses/archive/spr96/cs333/java/tutorial/java/anatomy/main.html
http://javabeginners.de/Grundlagen/main.php
http://spinfo.phil-fak.uni-koeln.de/spinfo-java-mainmethode.html?&L=0

Gruß Klaus
 
Also das geht schon etwas in die richtige Richtung, nur eben sollte ein Konstruktor eben nur ein Objekt erzeugen und keine weiteren Aktionen durchführen. Also Code immer dahin, wohin er gehört.

Wenn Du ein Auto herstellst, dann fährt das nicht nach München um dort etwas abzuholen.

Also wäre eher etwas wie folgt sinnvoll:
Code:
public static void main (String[] args) {
  SnakeGame game = new SnakeGame();
  game.run();
}
Halt so in der Art. Der Konstruktor erzeugt nur ein Objekt und dann wird irgendwas aufgerufen.

Oft gibt es auch mehrere Stati. Ein Spiel könnte also erstellt werden, initialisiert werden, dann ablaufen und dann in einem Ende Status sein. So gesehen gibt es dann evtl. unterschiedliche Funktionen:
- Konstruktor, der aufgerufen wird, wenn das Spiel erstellt wird. Da wird aber dann noch kein Spielbrett generiert.
- init() - da wird dann z.B. das Spielbrett generiert. Hat den Vorteil, dass man ein Spiel ggf. neu initialisieren kann.
- Dann läuft das Spiel. Da sind dann Funktionen denkbar, die vor einem Zug und nach einem Zug ausgeführt werden und der Zug selbst.
- Und dann eine Funktion, die das Ende beschreibt.

Das ist aber nur ein einfaches Beispiel, das ich mal grob skizziert habe. Oft hat man bei Applikationen zentrale Objekte. Ein Client hat ein Hauptfenster oder ein Server hat eine zentrale Verwaltung, die dann z.B. die Netzverbindungen verwaltet, die Business Objekte und all sowas....
 
Ich hab hier mal versucht den Aufbau des Programms ein bisschen anzureißen und meinen Konstruktor ausführlicher dargestellt.

Ist komischer Pseudocode gemischt in einem noch komischeren UML diagramm, aber ich habs echt versucht😕
Der original Quellcode ist hier: https://github.com/Baboon9/Snake

Wenn ich mir das so ansehe, dann weiß ich eigentlich garnicht warum ich nicht einfach alles static mache..
Es gibt dort einfach nur 2/3 Klassen die nicht static sein können
 

Anhänge

  • konstruktor.png
    konstruktor.png
    27,9 KB · Aufrufe: 30
Dein Konstruktor von Snake sieht ja schon ein bisschen anders aus als oben gepostet. Aber trotzdem spielt sich scheinbar das ganze Spiel im Konstruktor ab ?? Ich würde da mal auf @kneitzel verweisen und nur die Initialisierungen da drin vornehmen und für den Rest eine run-Methode machen.
 
Also bezüglich Objektorientiertem Design: Erstell richtige Objekte und benenne die Klassen entsprechend. Snake ist ja keine Schlange - das ist ja ein ganzen Spiel oder so.
Und dann wirklich Code immer dahin, wo er hin gehört. Konstruktor erstellt nur das Objekt und initialisiert einen Zustand. Es werden keine Aktionen durchgeführt.

Und dann implementierst Du das Objekt selbst. Was gehört alles dazu? Ein Auto hat Räder, einen Motor, einen Tacho, eine Richtung und Geschwindigkeit, ... Und was für Sachen kann das Auto machen? Beschleunigen, Lenken, Bremsen, Geschwindigkeit kann man abfragen, ....
Das wird dann alles implementiert. Ich kenne Dein Spiel nicht, aber es gibt ja so Snake Spiele, wo eine Schlange über den Bildschirm wandert und dabei Dinge frisst und dabei immer länger wird. dann hat so eine Schlange eine Richtung, eine Lokation des Kopfes, belegte Felder (Körper), ... Die Schlange kann abbiegen nach rechts oder links.

Evtl. kannst du ja auch ähnlich an Deine Applikation heran gehen.
 
@JStein52 Ja, ich wollte eigentlich garnicht mit dem kompletten Programm anfangen, deswegen habe ich Sachen gekürzt die ich für unwichtig hielt. Aber dann war wohl noch nicht klar was ich eigentlich mit den Klassen machen will und woher der parameter kam. Gut, das der Konstruktor nur die Initialisierung erledigen sollte sehe ich ein.

Das Programm spielt sich nicht nur im Konstruktor ab. Es gibt auch noch andere Funktionen in der Klasse. Es ist einfach Systemarchitektonischer Müll den ich da mal gemacht habe. Das wollte ich jetzt mal aufräumen.

Die Klasse Snake kümmert sich eigentlich nur wirklich um das Fenster. Alles andere hätte entweder static sein sollen oder in der Main initialisiert. Wie ich das im moment sehe. Eine "Game" oder "Snake Game" klasse wäre wohl womöglich auch überflüssig. Diese Endlosschleife im Konstruktor der bisherigen Version muss allerdings auf jeden fall da sein und am besten in der genannten run funktion stehen. Wichtig ist, dass das Spiel neu initialisiert werden kann, wenn es zuende ist. Dafür sollte es eine init Funktion auch geben. Komme wohl um diese Game klasse nicht drum rum.

@kneitzel Ja, es ist einfach das klassiche Snake Spiel gemeint, wo ein Quadrat gesteuert werden kann. Das quadrat kann mit Punkten kollidieren. Kollidiert die Schlange mit einem Punkt wird sie länger. Nach einer Zeitspanne wird das letzte Element der Schlange weg genommen und an erster Stelle der Schlange gesetzt wobei die Position des umgesetzten Elements abhängig von der Richtung die der Benutzer eingibt ist. Wenn die Schlange mit einem Element ihrer selbst kollidiert ist das Spiel vorbei. Kollidiert sie mit einem Punkt wird an einer freien Stelle ein neuer gesetzt.

Der Anwendungsfall könnte so aussehen:

Das Programm wird gestartet
Ein Fenster wird erstellt
Die Schlange wird auf dem Fenster plaziert
Ein Punkt wird auf dem Fenster plaziert
Warten auf Benutzereingabe
Die Bewegungsrichtung der Schlange wird geändert
Der Timer läuft aus
Die Das letzte Element der Schlange wird an die erste Stelle verschoben
Das letzte element der Schlange wird neu positioniert
Die Schlange kollidiert mit einem Punkt
-Die länge der Schlange erhöht sich um 1
-Auf richtigen Zeitpunkt warten um neues Element anzufügen
-Punkt neu platzieren
Die Schlange kollidiert mit sich selbst
-Auf Nutzereingabe warten
-- Spiel neu initialisieren
-- Fenster schließen

Daraus würde ich Die Klassen Fenster, Schlange, Punkt, Kollisionsdetektion, Timer, Benutzereingabe herleiten.


Ist ja schön und gut. Aber alle genannten Klassen könnten auch genauso gut static sein. Aber dann heißt es wieder "Das hat nichts mit Objektorientierung zu tun", "das ist zu viel Sichtbarkeit, das macht Fehler". Naja... ich werde auf jedenfall die Snake Klasse anpassen und mehr in die Main auslagern und in Game und Window Klassen teilen.

Danke an alle!
 
Ist ja schön und gut. Aber alle genannten Klassen könnten auch genauso gut static sein. Aber dann heißt es wieder "Das hat nichts mit Objektorientierung zu tun", "das ist zu viel Sichtbarkeit, das macht Fehler". Naja... ich werde auf jedenfall die Snake Klasse anpassen und mehr in die Main auslagern und in Game und Window Klassen teilen.
Anstatt nach gründen zu suchen, warum es nicht static sein sollte, such lieber nach Gründen, warum man es static machen sollte.

Das mag man zu Anfang manchmal als Einschränkung sehen, man verliert damit meistens aber mehr, als man gewinnt. Grad sowas wie Snake ist perfekt für OO, und vor allem im Hinblick auf größere Projekte die irgendwann kommen ist es sinnvoll, sich direkt vernünftig OO und MVC anzueignen
 

Zurück
Oben