Compiler-Fehler State Machine - Compiler Error

Nick9051

Mitglied
Hallo!

Ich entschuldige mich erstmal, falls ich das Forum falsch nutze. Das ist meine erste Frage hier.
Ich muss für eine Abgabe in der Universität eine Mikrowelle als State Machine programmieren. Beim testen des Programms in meiner Main funktioniert alles fehlerfrei. Lade ich die Aufgabe aber hoch (wo der Code nochmals getestet wird) bekomme ich einen Compiler-Error.

Das Diagramm lässt sich leider nicht als Bild hochladen. Wenn ihr das brauchen solltet, dann versuche ich das nochmal irgendwie anders.

Ich habe die folgenden Klassen:

Microwave
public class Microwave {

State state = State.inactive; <- ist das eventuell der Fehler?


public State getState() {
System.out.println(state);
return state;
}

static void beep() {
System.out.println("BEEEEEEEP o.o");
}
static void boop() {
System.out.println("BOOOOP *~*");
}
static void mjamm() {
System.out.println("MJAMM *o*");
}

public void openDoor() {
state.openDoor(this);
}

public void closeDoor() {
state.closeDoor(this);
}

public void addTime() {
state.addTime(this);
}

public void timerUp() {
state.timerUp(this);
}

public void startMicrowaving() {
state.startMicrowaving(this);
}
}

State:
public abstract class State {
public static final Heating heating = new Heating();
public static final Open open = new Open();
public static final Inactive inactive = new Inactive();

public abstract void openDoor(Microwave a);
public abstract void closeDoor(Microwave a);
public abstract void addTime(Microwave a);
public abstract void timerUp(Microwave a);
public abstract void startMicrowaving(Microwave a);
}

Drei Subklassen von State, die alle die selben Funktionen haben, aber je nach aktuellem Status andere Ausgaben haben.
Beispiel Inactive:


public class Inactive extends State {

public String printState() {
return "Inactive";
}
@Override
public void openDoor(Microwave a) {
a.state = State.open;
}

@Override
public void closeDoor(Microwave a) {
System.out.println("Die Tuer geht nicht noch fester zu!");
}

@Override
public void addTime(Microwave a) {
Microwave.beep();
}

@Override
public void timerUp(Microwave a) {
System.out.println("Mikrowelle ist inaktiv!");
}

@Override
public void startMicrowaving(Microwave a) {
Microwave.beep();
a.state = State.heating;
}
}
 
Aus dem Bauch heraus sehe ich keine offensichtlichen Fehler (deswegen auch die Frage). Auffällig ist, dass die Methoden beep & Co static sind - soll da so sein?

Ich würde noch mal wirklich die Aufgabenstellung Schritt für Schritt durchgehen, welche Methoden (insbesondere ob Statisch oder nicht) mit welchen Bezeichnungen & Parametern die haben sollen. Wenn es bei dir kompiliert, aber auf der Test-Umgebung nicht heißt das nämlich vermutlich, dass die Klasse auf der Testumgebung, die deinen Code aufrufen will, eine Methode erwartet, die so nicht da ist.

Nachtrag: Wichtig ist da wirklich die exakte Schreibweise, Groß & Kleinschreibung ist extrem relevant
 
Wie wird es denn hochgeladen? Lädst du wirklich deine source Code Dateien hoch, oder kopierst du den Text irgendwo rein?
Bei zweiteren könnte ich mir vorstellen, dass dort evtl der Fehler liegt. Angenommen du kopierst alles in ein Fenster, wird es evtl als eine Datei gesehen und Java erlaubt nur eine Public class pro Datei
 
Was mir spontan noch auffaellt ist die printState() Methode, der Name und der Body passen nicht ganz. Der name sagt mir sie wir den State ( zb auf die Console) ausgeben, aber tatsaechlich wird ein String zurueckgegeben. evtl wird die Methode ja aufgerufen und es wird void erwartet?
 
Die Funktion habe ich jetzt weggenommen, da sie nicht erforderlich war. Leider hat die Abgabe noch immer einen Compile Error.
In der Aufgabenstellung steht folgendes:
"Fügen Sie einen Getter für den aktuellen Zustand hinzu."
Meines Erachtens nach habe ich das schon. Liege ich damit möglicherweise falsch?
 
Also getState passt eigentlich. Sie sollte zwar nicht den State auf der Console ausgeben, aber daher kommt nicht der Compiler Fehler. Das State Attribut sollte auch privat sein, aber auch das verursacht keinen Compiler Fehler. Kannst du uns die komplette Aufgabenstellung zu verfuegung stellen?
 
Kann der Fehler etwas damit zu tun haben, dass bei der Eingabe in der Main Methode:
System.out.println(microwave.state);

Inactive@5e91993f in der Konsole angegeben wird statt nur Inactive?
 
dann löse ihn ... ohne static
Das Problem ist, wie oben beschrieben, dass ich den Fehlertext nicht einsehen kann, sondern nur von einem Compile Error weiß.
Dieser tritt bei mir aber nicht auf, sonst würde ich das Debugging ja anhand der Fehler machen 😅

Die static-Problematik ist, wie in meinem letzten Kommentar beschrieben, natürlich auch schon behoben. Der Fehler bleibt.
 
"~ : kennzeichnet die default-Sichtbarkeit" steht oben in der Beschreibung und in der Klasse "Microwave" steht ~beep(), ~boop() und ~mjamm().

Daraus hatte ich eigentlich geschlossen, dass die Methoden die default Sichtbarkeit haben müssen.
 
Stimmt. Ggf. mal die Ausgabe anpassen für beep/boop gemäß gemäß der Vorgabe (Wobei das eigentlich nicht zu einem Compile Error führen sollte) Mir gehen die Ideen aus
 
Probiere beides einmal aus, einmal mit public und einmal mit protected. Wir haben keine weiteren Informationen über das Backend und es kann durchaus sein, dass es daran liegt.

Unabhängig davon, die anderen, hier nicht gezeigten States hast du doch auch implementiert und hochgeladen oder?

Und die Ausgabe Strings stimmen auch genau?
 
Die Ausgabe-Strings machen alle das, was sie sollen. Der State wird auch gewechselt und die Ausgabe bzw. die Methoden liefern dementsprechend ein anderes Ergebnis.

Ich kommentiere hier nochmal alle Klassen einzeln. Das hilft vielleicht bei dir Übersicht.

Ich danke euch allen vielmals!!
 
[CODE lang="java" title="Microwave"]
public class Microwave {

State state = State.inactive;

public State getState() {
return this.state;
}
void beep() {
System.out.println("BEEEEEEEP");
}
void boop() {
System.out.println("BOOOOP");
}
void mjamm() {
System.out.println("MJAMM");
}

public void openDoor() {
state.openDoor(this);
}

public void closeDoor() {
state.closeDoor(this);
}

public void addTime() {
state.addTime(this);
}

public void timerUp() {
state.timerUp(this);
}

public void startMicrowaving() {
state.startMicrowaving(this);
}
}
[/CODE]
 

Anhänge

[CODE lang="java" title="State"]public abstract class State {
static protected Heating heating = new Heating();
static protected Open open = new Open();
static protected Inactive inactive = new Inactive();

public abstract void openDoor(Microwave a);
public abstract void closeDoor(Microwave a);
public abstract void addTime(Microwave a);
public abstract void timerUp(Microwave a);
public abstract void startMicrowaving(Microwave a);
}[/CODE]
 

Anhänge

Zuletzt bearbeitet:
[CODE lang="java" title="Heating"]
public class Heating extends State {



public void openDoor(Microwave a) {
a.boop();
a.state = State.open;
}


public void closeDoor(Microwave a) {
//System.out.println("Die Tuer geht nicht noch fester zu!");
}


public void addTime(Microwave a) {
a.beep();


}


public void timerUp(Microwave a) {
for (int i = 3; i>0; i--) {
a.beep();
}
a.state = inactive;

}

public void startMicrowaving(Microwave a) {
a.boop();
//System.out.println("Mikrowelle laeuft schon");

}
}
[/CODE]
 

Anhänge

[CODE lang="java" title="Inactive"]
public class Inactive extends State {



public void openDoor(Microwave a) {
a.state = open;


}


public void closeDoor(Microwave a) {
//System.out.println("Die Tuer geht nicht noch fester zu!");

}


public void addTime(Microwave a) {
a.beep();

}


public void timerUp(Microwave a) {
//System.out.println("Mikrowelle ist inaktiv!");
}

public void startMicrowaving(Microwave a) {
a.beep();
a.state = heating;

}

}
[/CODE]
 

Anhänge

[CODE lang="java" title="Open"]
public class Open extends State {



public void openDoor(Microwave a) {
//System.out.println("Die Tuer ist schon offen!");

}


public void closeDoor(Microwave a) {
a.state = inactive;

}


public void addTime(Microwave a) {
//System.out.println("Die Tuer ist offen!");
}


public void timerUp(Microwave a) {
//System.out.println("Die Tuer ist offen!");
}


public void startMicrowaving(Microwave a) {
//System.out.println("Die Tuer ist offen!");
}

}
[/CODE]
 

Anhänge

das state interface? die main ? was passiert? das sind klassen... so in dem format würde der compiler alles weg werfen da sie nicht benutzt werden
 
das state interface? die main ? was passiert? das sind klassen... so in dem format würde der compiler alles weg werfen da sie nicht benutzt werden
Die main liegt auf den uni Servern in die ich die Klassen hochlade. Die kann ich leider genau so wenig einsehen wie alle anderen Informationen. Eine eigene Main mit stumpfen Ausführungen aller Befehle in jedem Status habe ich zum testen geschrieben. Die ist nur ohne Aussagekraft. Ich kann sie trotzdem neu schreiben und hochladen, wenn das gewünscht ist.

State ist als abstrakte Klasse gedacht statt als Interface. Das wurde uns so in den Vorlesungen gezeigt.
 
du kannst das nicht programmieren ohne eine main zum testen zu haben

1. welche teile funktionieren denn?
2, welche nicht ?
3. wo funtkionieren sie nich ?

... ohne main kannst du das nicht sagen

wenn du 1en durchlauf von allen kombinationen schaffst wirst du in der anderen main alle durchläufe schaffen... nur du kannst nicht einzelne komponenten testen wenn "dein test" das fertige programm ist .. das unfktioniert nich ... wird auch nie funktionieren

Außerdem hab ich noch nie von einer "gedachten klasse" gehört... entweder ist sie da oder nicht und hat schnittstellen
 
Probier das mal so ("public" bei den Klassen nicht vergessen):

Java:
public class Microwave {
    State state = State.inactive;

    public State getState() {
        return this.state;
    }

    void beep() {
        System.out.println("BEEEEEEEP");
    }

    void boop() {
        System.out.println("BOOOOP");
    }

    void mjamm() {
        System.out.println("MJAMM");
    }

    public void openDoor() {
        state = state.openDoor(this);
    }

    public void closeDoor() {
        state = state.closeDoor(this);
    }

    public void addTime() {
        state = state.addTime(this);
    }

    public void timerUp() {
        state = state.timerUp(this);
    }

    public void startMicrowaving() {
        state = state.startMicrowaving(this);
    }
}

 abstract class State {
    public static Heating heating = new Heating();
    public static Open open = new Open();
    public static Inactive inactive = new Inactive();

    public abstract State openDoor(Microwave a);

    public abstract State closeDoor(Microwave a);

    public abstract State addTime(Microwave a);

    public abstract State timerUp(Microwave a);

    public abstract State startMicrowaving(Microwave a);
}

 class Open extends State {
    public State openDoor(Microwave a) {
        //System.out.println("Die Tuer ist schon offen!");
        return this;
    }

    public State closeDoor(Microwave a) {
        return inactive;
    }

    public State addTime(Microwave a) {
        //System.out.println("Die Tuer ist offen!");
        return this;
    }

    public State timerUp(Microwave a) {
        //System.out.println("Die Tuer ist offen!");
        return this;
    }

    public State startMicrowaving(Microwave a) {
        //System.out.println("Die Tuer ist offen!");
        return this;
    }
}

 class Inactive extends State {
    public State openDoor(Microwave a) {
        return open;
    }

    public State closeDoor(Microwave a) {
        //System.out.println("Die Tuer geht nicht noch fester zu!");
        return this;
    }

    public State addTime(Microwave a) {
        a.beep();
        return this;
    }

    public State timerUp(Microwave a) {
        //System.out.println("Mikrowelle ist inaktiv!");
        return this;
    }

    public State startMicrowaving(Microwave a) {
        a.beep();
        return heating;
    }
}

 class Heating extends State {
    public State openDoor(Microwave a) {
        a.boop();
        return open;
    }

    public State closeDoor(Microwave a) {
        //System.out.println("Die Tuer geht nicht noch fester zu!");
        return this;
    }

    public State addTime(Microwave a) {
        a.beep();
        return this;
    }

    public State timerUp(Microwave a) {
        for (int i = 3; i > 0; i--) {
            a.beep();
        }
        return inactive;
    }

    public State startMicrowaving(Microwave a) {
        a.boop();
        //System.out.println("Mikrowelle laeuft schon");
        return this;
    }
}
 
OMG bin ich doof, hab den Fehler: "Referencing subclass Heating from superclass State initializer might lead to class loading deadlock"

Schreibe:

Java:
public abstract class State {
    public abstract State openDoor(Microwave a);

    public abstract State closeDoor(Microwave a);

    public abstract State addTime(Microwave a);

    public abstract State timerUp(Microwave a);

    public abstract State startMicrowaving(Microwave a);
}

Und mach dann so etwas:

Java:
    public State closeDoor(Microwave a) {
        return new Inactive();
    }
 
Hier noch einmal komplett:

Java:
package ...;

public class Microwave {
    private State state = new Inactive();

    public State getState() {
        return this.state;
    }

    void beep() {
        System.out.println("BEEEEEEEP");
    }

    void boop() {
        System.out.println("BOOOOP");
    }

    void mjamm() {
        System.out.println("MJAMM");
    }

    public void openDoor() {
        state = state.openDoor(this);
    }

    public void closeDoor() {
        state = state.closeDoor(this);
    }

    public void addTime() {
        state = state.addTime(this);
    }

    public void timerUp() {
        state = state.timerUp(this);
    }

    public void startMicrowaving() {
        state = state.startMicrowaving(this);
    }
}

public abstract class State {
    public abstract State openDoor(Microwave a);

    public abstract State closeDoor(Microwave a);

    public abstract State addTime(Microwave a);

    public abstract State timerUp(Microwave a);

    public abstract State startMicrowaving(Microwave a);
}

public class Open extends State {
    public State openDoor(Microwave a) {
        //System.out.println("Die Tuer ist schon offen!");
        return this;
    }

    public State closeDoor(Microwave a) {
        return new Inactive();
    }

    public State addTime(Microwave a) {
        //System.out.println("Die Tuer ist offen!");
        return this;
    }

    public State timerUp(Microwave a) {
        //System.out.println("Die Tuer ist offen!");
        return this;
    }

    public State startMicrowaving(Microwave a) {
        //System.out.println("Die Tuer ist offen!");
        return this;
    }
}

public class Inactive extends State {
    public State openDoor(Microwave a) {
        return new Open();
    }

    public State closeDoor(Microwave a) {
        //System.out.println("Die Tuer geht nicht noch fester zu!");
        return this;
    }

    public State addTime(Microwave a) {
        a.beep();
        return this;
    }

    public State timerUp(Microwave a) {
        //System.out.println("Mikrowelle ist inaktiv!");
        return this;
    }

    public State startMicrowaving(Microwave a) {
        a.beep();
        return new Heating();
    }
}

public class Heating extends State {
    public State openDoor(Microwave a) {
        a.boop();
        return new Open();
    }

    public State closeDoor(Microwave a) {
        //System.out.println("Die Tuer geht nicht noch fester zu!");
        return this;
    }

    public State addTime(Microwave a) {
        a.beep();
        return this;
    }

    public State timerUp(Microwave a) {
        for (int i = 3; i > 0; i--) {
            a.beep();
        }
        return new Inactive();
    }

    public State startMicrowaving(Microwave a) {
        a.boop();
        //System.out.println("Mikrowelle laeuft schon");
        return this;
    }
}

Bitte kurzes Feedback, ob es klappte...
 
was wurde dir in der Vorlesung bezüglich der State klasse beschrieben ? diese macht als abstrakte klasse bzw interface keinen sinn nach der aufgaben stellung
da die Klasse eine "statemachine" darstellen sollte... die 3 zustände vertritt ... eine abstrakte kann das nich!
 
du bist jetzt in der Zwickmühle da in der Aufgabe drin steht "Die statemachine... " eine statemachine ist meines erachtens für das verwalten von mehreren zuständen verantworlich und absolut das gegenteil von abstrakt oder interface

dir wurde gezeigt dass du diese abstrakt machen kannst ( wieso auch immer ) nur diese abstraktion macht keinen sinn da die states keinerlei gemeinsamkeiten haben ausser dass sie die mikrowelle kennen ( das ist die einzige gemeinsamkeit die du nicht implementiert hast )
wenn du den abstrakten weg gehst kapier ich nicht für was du die states brauchst?? weil dann die Mikrowelle für die State verwaltung zuständig ist


es würde mehr sinn machen wenn die open inactive und closed interfaces wären und die state klasse diese 3 dann implementiert dann hast du eine state machine... aber keine ahnung ... solange man nich weis wies gemacht werden sollte ist es schwer zu sagen
 
Das ganze wird laut Vorlesung nach MethodDispatch programmiert.
Es funktioniert auch als Statemachine, auch wenn sie möglicherweise etwas unkonventionell aussieht.
Die Ausgaben in meiner Konsole beweisen mir das ganze. Lässt sich auch leicht testen, ich habe meine Klassen, außer meiner inzwischen wieder leeren Main, ja alle hier hochgeladen.

Eine Frage: Als ich versucht habe mir den Zustand ausgeben zu lassen habe ich z.B. Inactive@ak6kaiejo1 (Nicht der Wert, nur ein Beispiel) ausgegeben bekommen. Das ist der Speicherort und nicht der Wert, richtig?
Könnte das mit dem Compile Error zusammenhängen?
 
aus deinem zustandsdiagramm kann ich raus lesen dass alle methoden ohne parameter funktionieren deswegen wird das methoddispatch sie nicht finden per reflection

würde dir raten mal die state klasse zu erweitern es ist ja eine katastrophpe dass du bei jeder methode die dämliche mikrowelle übergibst!

wie wärs mit dem in der state klasse vllt? dann fallen auch die dämlichen parameter weg
Java:
  protected Mikrowelle mikro;

  public State(Mikrowelle mikro) {
    this.mikro = mikro;
  }
 
@Nick9051 Kannst du bitte noch einmal rekapitulieren, was genau in eurer Vorlesung gesagt wurde, in welcher "Form" ihr die State-Maschine implementieren sollt? Das wäre sehr hilfreich, um eine Vorstellung davon zu bekommen, wo der Fehler sein könnte.

Die "reine" Aufgabenstellung lässt zu viele Implementierungsdetails offen. Ich seh das auch so wie Mart.
 
Ehm das ist architektonisch keine gute Idee. Eine Mikrowelle kennt ihren State, aber State kennt keine Mikrowelle. Ein State arbeitet auf einer Mikrowelle für einen Statusübergang. Von daher ist es so, wie es jetzt ist architektonisch sauberer.

Aber ja, ich sehe es wie @jari - einzige was übrig bleibt ist die genaue Definition von Method Dispatch, da war google auch wenig Hilfreich 🙂
 
das state pattern hier ist aber denke ich nicht mal so toll anzuwenden

du hast ne abstrakte kklasse die 5 methodne vorgibt ( sollte man aus clean code sicht auch nicht machen) dann gibts 2 klassen wo jede nur minimal was benutzen kann... was ist wenn das erwetiert wird? der code erweitert sich exponentiell mit MINIMALER wirksamkeit... dann wirds zu einem anti pattern
 

Zurück
Oben