API fluida con herencia y genéricos

Estoy escribiendo una API fluida para configurar e instanciar una serie de objetos de "mensaje". Tengo una jerarquía de tipos de mensajes.

Para poder acceder al método de subclases cuando se usa la API fluida, utilicé genéricos para parametrizar las subclases y hacer que todos los métodos fluidos (que comienzan con "con") devuelvan el tipo genérico. Tenga en cuenta que omití la mayor parte del cuerpo del método fluido; mucha configuración continúa en ellos.

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

    protected Message() {

    }

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

Las subclases concretas redefinen el tipo genérico de manera similar.

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;
    }
}

Este código funciona, es decir, puedo instanciar cualquiera de las clases y usar todos los métodos fluidos:

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

Llamar a los métodos fluidos en cualquier orden es un objetivo principal aquí.

Sin embargo, el compilador advierte que todosreturn (T) this son inseguros

Tipo de seguridad: conversión sin marcar de mensaje a T

No estoy seguro de cómo podría reorganizar la jerarquía para que este código sea realmente seguro. Aunque funciona, el uso de genéricos de esta manera se siente realmente complicado. Especialmente, no puedo prever situaciones en las que se produzcan excepciones de tiempo de ejecución si solo ignoro las advertencias. Habrá nuevos tipos de mensajes, así que necesito mantener el código extensible. Si la solución es evitar la herencia por completo, también me gustaría obtener sugerencias de alternativas.

Existenotro preguntas aquí en SO que abordan un problema similar. Apuntan a una solución donde todas las clases intermedias son abstractas y declaran un método comoprotected abstract self(). Aún así, al final no es seguro.

Respuestas a la pregunta(5)

Su respuesta a la pregunta