Leere vererbte Interface-Methoden

BoGJav

Neues Mitglied
Hallo,

die Frage in kurz: Wie gehe ich mit leeren vererbten Interface-Methoden um? Sollte ich lieber eine abstrakte Klasse nutzen?

die Frage mit Kontext:


Ich programmiere aktuell einen HTTP-Server. Jede mögliche URL (z.B. /home oder /login) hat ihren eigenen ContextHandler (z.B. HomeContextHandler oder LoginContextHandler). Alle ContextHandler haben eine Gemeinsamkeit: z.B. das Senden einer Antwort. Aus diesem Grund gibt es eine Elternklasse. Diese heißt ganz kreativ: ContextHandler. Diese Klasse erkennt auch, welche HTTP-Methode aufgerufen wurde und startet die jeweilige Methode (onPost(), onGet(), onTrace(), onHead() usw.). Diese Methoden sind, für die Übersichtlichkeit, in einem Interface (HttpMethodsHandler) definiert. Die ContextHandler Klasse implementiert dieses Interface und die Erben des ContextHandlers müssen die jeweiligen Methoden implementieren.
Jetzt das Problem: nicht alle ContextHandlers Erben brauchen alle Methoden von HttpMethodsHandler, da manche HTTP-Methoden nicht unterstützt werden.
Z.B. braucht /home keine Post-Methode.
Da aber alle Interface-Methoden implementiert werden müssen, taumeln die mit einem lehren Body in meinen ContextHandlers rum. Das stört mich zwar nicht, aber gibt es eine bessere Lösung?

Ich wünsche Euch noch einen schönen Abend.
 
Vielleicht ist Vererbung einfach das falsche Werkzeug, und vielleicht wäre z.B. ein Strategiemuster und ein paar statische Methoden eine bessere Lösung.

Nur mal so aus der Hüfte geschossen.
 
Deine eigentliche Frage ist eine andere, naemlich: Was soll passieren wenn die nicht benoetigten Methoden aufgerufen werden?

Nehmen wir mal folgende Schnittstelle an:

Java:
public interface Actions {
    public abstract String performK();
    public abstract String performL();
    public abstract String performQ();
}

Wenn wir jetzt eine Klasse wollen welche nur die Aktion "L" kann wuerde das so aussehen:

Java:
public class LOnlyActions implements Actions {
    @Override
    public String performK() {
        return null;
    }
   
    @Override
    public String performL() {
        return "Logic went here";
    }
   
    @Override
    public String performQ() {
        return null;
    }
}

Nun stellt sich die Frage "Was soll passieren wenn die Nicht-Implementierten Methoden aufgerufen werden?", in diesem Fall retournieren wir einfach null, aber das kann gut oder auch nicht sein. Das kommt immer darauf an was genau man will. Oft wird auch eine UnsupportedOperationException geworfen:

Java:
public class LOnlyActions implements Actions {
    @Override
    public String performK() {
        throw new UnsupportedOperationException("Action K is not implemented.");
    }
   
    @Override
    public String performL() {
        return "Logic went here";
    }
   
    @Override
    public String performQ() {
        throw new UnsupportedOperationException("Action Q is not implemented.");
    }
}

Wenn man jetzt sehr viele Implementationen von Actions hat, und diese immer nur eine oder zwei Methoden brauchen, muss man das Konstant wiederholen, um dies abzumildern kann man sich eine abstrakte Klasse definieren:

Java:
public abstract class AbstractActions implements Actions {
    @Override
    public String performK() {
        throw new UnsupportedOperationException("Action K is not implemented.");
    }
   
    @Override
    public String performL() {
        throw new UnsupportedOperationException("Action L is not implemented.");
    }
   
    @Override
    public String performQ() {
        throw new UnsupportedOperationException("Action Q is not implemented.");
    }
}

Dann kann man die eigentlichen Implementierungen etwas rauscharmer haben:

Java:
public class LOnlyActions extends Actions {
    @Override
    public String performL() {
        return "Logic went here";
    }
}

Aber die eigentliche Frage ist halt immer: Was soll passieren wenn die nicht implementierten/unterstuetzten Funktionen aufgerufen werden?
 
In diesem Fall würde ich Interface Default Methoden verwenden. Wenn ein HTTP-Verb bzw. eine HTTP Methode von einem Handler nicht unterstützt wird, ist das sinnvollste, hier den HTTP Status Code 405 "Method Not Allowed" zurückzugeben:
Java:
public interface HttpMethodsHandler {
  default void onGet(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  default void onPost(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  default void onPut(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  default void onPatch(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  default void onHead(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  default void onOptions(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  default void onDelete(HttpResponseWriterOrWhatever w) {w.sendStatus(405);}
  ...
}
Das kann ja immer der Default sein.
 
Zuletzt bearbeitet:
Stimmt, ich vergesse immer dass es default Methoden gibt.

Setzt aber voraus man kann die Schnittstelle aendern, klang jetzt in dem Thema nicht so.
 
Wieso Schnittstelle ändern? Die Schnittstelle besteht ja einfach nur aus den Methoden für die einzelnen http Verben.
Und die einzelnen Handler implementieren nur die Methoden, die sie unterstützen. Der Rest behält ihre Default Implementierung.
Ich sehe da noch keine Änderung einer Schnittstelle.
 
Danke für Eure schnellen und ausführlichen Antworten!

Deine eigentliche Frage ist eine andere, naemlich: Was soll passieren wenn die nicht benoetigten Methoden aufgerufen werden?
Darum kümmert sich mein ContextHandler. Dieser liest die Methode und gibt entweder einen "Not implemented 501" oder "Method not allowed 405" Fehler zurück an den Client. Entschuldigung, das habe ich vergessen in meine Frage reinzuschreiben.

Wenn man jetzt sehr viele Implementationen von Actions hat, und diese immer nur eine oder zwei Methoden brauchen, muss man das Konstant wiederholen, um dies abzumildern kann man sich eine abstrakte Klasse definieren
Daran habe ich auch schon gedacht. Ich habe aber Zugriff auf die Schnittstelle, weswegen ich das Interface ändern kann. Könnte ich die Schnittstelle nicht ändern, wäre das die beste Möglichkeit.

In diesem Fall würde ich Interface Default Methoden verwenden. Wenn ein HTTP-Verb bzw. eine HTTP Methode von einem Handler nicht unterstützt wird, ist das sinnvollste, hier den HTTP Status Code 405 "Method Not Allowed" zurückzugeben
Davon habe ich noch nie gehört. Scheint aber eine schöne Lösung zu sein. Danke vielmals.
 

Neue Themen


Zurück
Oben