Java: anulación del tipo de retorno de la interfaz extendida cuando el tipo de retorno usa genéricos para los tipos de parámetros de método propios

Me topé con una curiosidad por la herencia de Java, y quería que pidieras mejores ideas sobre eso:

Asuma dos interfaces A y A1

Interface A1 extiende A

Interface A tiene un método que devuelve un tipo genérico.

El tipo genérico sería comoGenericType<T>.

na idea básica ahora es cambiar este tipo de retorno genérico deGenericType<Object> en la interfaz A enGenericType<String> en la interfaz A1

Bueno parece ser fácil al principio (las cosas malas vendrán más adelante)

Declaramos la interfaz A como

public interface InterfaceA {
  public GenericType<? extends Object> getAGenericType();  
}

e Interfaz A1 como

public interface InterfaceA1 extends InterfaceA
{
  @Override
  public GenericType<String> getAGenericType();
}

omo ves, nos vemos obligados a escribirGenericType<? extends Object> en la interfaz A para permitir reemplazarla con "subclases" genéricas. (De hecho, el parámetro genérico del tipo genérico se subclasifica, no el tipo genérico en sí mismo)

Ahora suponga que GenericType tiene su propio método con el siguiente aspecto:

public interface GenericType<D>
{
  public void doSomethingWith( D something );
}

Ahora intentar crear una instancia de A1 funciona muy bien.

En lugar de tratar de crear una instancia A apestará. Para ver por qué mira esta clase de "usar la interfaz":

public class LookAtTheInstance
{
  @SuppressWarnings("null")
  public static void method()
  {
    InterfaceA a = null;
    InterfaceA1 a1 = null;

    GenericType<String> aGenericType = a1.getAGenericType();

    GenericType<? extends Object> aGenericType2 = a.getAGenericType();
    Object something = null;
    aGenericType2.doSomethingWith( something );
  }
}

Usted pregunta: "¿Y ahora?"

No funciona en las últimas líneas. De hecho, el parámetro "algo" ni siquiera es del tipo "Objeto", es del Tipo "? Extiende el Objeto". Por lo tanto, no puede pasar el tipo de "Objeto" declarado. No puedes pasar nada en absoluto.

e modo que terminas declarando interfaces agradables que, como resultado, no se pueden crear instancias correctamente.

¿Tiene ideas de cómo modelar un caso de uso de este tipo, donde las subclases tendrán que anular el tipo de retorno, mientras que el tipo de retorno es un genérico?

¿O cómo andarías con un caso de este tipo?

¿O solo me falta un punto simple en la declaración genérica y mi ejemplo es posible de esta manera?

----------- (1) editar debido a las respuestas -----------

Una idea básica muy buena es hacer que la interfaz sea más abstracta. Tuve exactamente la misma idea primero, pero ... (esto tiene que venir)

Suponga que hace esto:

Presentamos una nueva interfaz AGeneric

public interface InterfaceAGeneric<T>{
  public GenericType<T> getAGenericType();
}

Ahora tendremos que extender A y A1 desde esta nueva interfaz:

public interface InterfaceA extends InterfaceAGeneric<Object>{}
public interface InterfaceA1 extends InterfaceAGeneric<String>{}

Eso funciona bien, aunque rompe el camino de la herencia original.

Si queremos que A1 siga siendo extensible desde A, tenemos que cambiar A1 a

public interface InterfaceA1 extends InterfaceA, InterfaceAGeneric<String>{}

y hay un problema otra vez. Esto no funciona, ya que extendemos indirectamente la misma interfaz con diferentes tipos genéricos. Desafortunadamente, esto no está permitido.

¿Ves el problema?

-

Y para señalar otra circunstancia:

Si lanzas elGenericType<? extends Object> aGenericType<Object> obviamente funciona. Ejemplo

public class LookAtTheInstance
{
  public static void main( String[] args )
  {
    InterfaceA a = new InterfaceA()
    {
      @Override
      public GenericType<? extends Object> getAGenericType()
      {
        return new GenericType<Object>()
        {
          @Override
          public void doSomethingWith( Object something )
          {
            System.out.println( something );
          }
        };
      }
    };
    ;

    @SuppressWarnings("unchecked")
    GenericType<Object> aGenericType2 = (GenericType<Object>) a.getAGenericType();

    Object something = "test";
    aGenericType2.doSomethingWith( something );
  }  
}

Por lo tanto, me parece que la resolución del tipo de parámetro del método

public interface GenericType<D extends Object>
{
  public void doSomethingWith( D something );
}

Está Mal

Si D está unificado con "? Extiende Objeto" ¿por qué el tipo de parámetro no está obligado a ser "Objeto"?

¿No tendría esto más sentido?

Respuestas a la pregunta(6)

Su respuesta a la pregunta