Fluent-API mit Vererbung und generics

Schreibe ich eine fluent-API zu konfigurieren und instanziieren eine Reihe von "message" Objekte. Ich habe eine Hierarchie von Nachrichtentypen.

Zugriff auf die Methode von Subklassen, wenn mithilfe der fluent-API, die ich verwendet, Generika einstellen der Unterklassen und stellen Sie alle fließend Methoden (beginnen mit "mit") zurück, die den generischen Typ. Beachten Sie, dass ich ausgelassen, die meisten des Körpers, der fließend Methode; eine Menge von Konfiguration geht auf in Ihnen.

public abstract class Message<T extends Message<T>> {

    protected Message() {

    }

    public T withID(String id) {
        return (T) this;
    }
}

Die konkrete Unterklassen redefinieren der generische Typ ähnlich.

public class CommandMessage<T extends CommandMessage<T>> extends Message<CommandMessage<T>> {

    protected CommandMessage() {
        super();
    }

    public static CommandMessage newMessage() {
        return new CommandMessage();
    }

    public T withCommand(String command) {
        return (T) this;
    }
}

public class CommandWithParamsMessage extends
    CommandMessage<CommandWithParamsMessage> {

    public static CommandWithParamsMessage newMessage() {
        return new CommandWithParamsMessage();
    }

    public CommandWithParamsMessage withParameter(String paramName,
        String paramValue) {
        contents.put(paramName, paramValue);
        return this;
    }
}

Dieser code funktioniert, d.h. ich kann instanziieren alle Klassen und alle fließend Methoden:

CommandWithParamsMessage msg = CommandWithParamsMessage.newMessage()
        .withID("do")
        .withCommand("doAction")
        .withParameter("arg", "value");

Aufruf des fluent-Methoden in beliebiger Reihenfolge, ist ein wichtiges Ziel der hier.

Jedoch der compiler warnt, dass alle return (T) this unsicher sind.

Type safety: Unchecked cast from Nachricht an T

Ich bin mir nicht sicher, wie ich könnte die Reorganisation der Hierarchie, damit dieser code wirklich sicher. Obwohl es funktioniert, ist der Einsatz von Generika in dieser Mode fühlt sich wirklich verworren.
Vor allem, bin ich nicht in der Lage vorauszusehen, Situationen, in denen Laufzeit-Ausnahmen wird passieren, wenn ich einfach die Warnungen ignorieren.
Es wird neue message-Typen, so muss ich den code erweiterbar.
Wenn die Lösung zu vermeiden, die erbschaft insgesamt möchte ich auch erhalten, Vorschlag von alternativen.

Gibt es andere Fragen hier SO, dass die Adresse einem ähnlichen Problem. Sie zeigen eine Lösung, bei der alle zwischen Klassen sind Abstrakt, und deklarieren Sie eine Methode, wie protected abstract self(). Dennoch, am Ende ist es sicher nicht.

  • Der code ist nicht sicher, obwohl, ist es? Woher wissen Sie, dass Message ist der Typ T?
  • da T extends Message<T>.
  • Beachten Sie aber, Gefahren der Korrelation von Subtyp-Polymorphismus generische Polymorphie
  • Das nicht nur bedeuten, dass der parameter erweitert Botschaft? Die Nachricht, die verwendet wird ist nicht unbedingt der Typ T?
  • die Nachricht, die verwendet wird (werden), ist vom Typ T, weil die Unterklassen definieren Sie T als eine eigene Art, wenn die Erweiterung Message<T extends Message>
  • aber die abstrakte API nicht wissen, dass immer für wahr halten
  • Versuchen Sie einfach, mit public Message<T> withID(String id) {return this;} statt public T withID(String id) {return (T) this;}. Tun Sie dasselbe für CommandMessage als gut.
  • Ich versuchte, dass jetzt die withCommand gibt den falschen Typ und ich bekomme eine Fehlermeldung: The method withCommand(String) is undefined for the type Message<CommandMessage<CommandWithParamsMessage>>
  • Ich bin nicht davon überzeugt, dass eine Vererbungshierarchie ist der beste Ansatz, um Ihren Fall.
  • Eigentlich denke ich es ist. Im wesentlichen, was OP braucht, ist für die superclass-Methoden zum zurückgeben von der Klasse des aktuellen Objekts, ruft Sie, und durch das design von Java, wir sind beschränkt auf Generika. Beachten Sie, dass diese Frage ähnlich wie die Frage: stackoverflow.com/questions/4031857/...
  • Siehe auch stackoverflow.com/q/7354740/685806

InformationsquelleAutor Boj | 2014-05-19
Schreibe einen Kommentar