he tropezado con una curiosidad en la herencia de java, y yo quería que usted pide más y mejores ideas que:

Asumir dos interfaces a y A1

Interfaz A1 extiende Un

Interfaz tiene un método que devuelve un tipo genérico.

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

Una idea básica es ahora para cambiar esta genérica tipo de retorno de
GenericType<Object> en Una Interfaz en
GenericType<String> en la Interfaz A1

Bien parece fácil a primera (cosas malas vendrá más tarde)

Declaramos Una Interfaz como

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

y la Interfaz de A1 como

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

Como se puede ver estamos obligados a escribir GenericType<? extends Object> en la Interfaz de la misma para permitir el reemplazo con genérico basado en «subclases».
(De hecho, el parámetro genérico de la generictype es una subclase no el tipo genérico de sí mismo)

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

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

Ahora tratando de crear instancias de A1 de las grandes obras.

Más bien intentar crear una instancia de Una va a chupar. A ver ¿por qué buscar en este «uso de la interfaz de» clase:

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» no es ni siquiera de tipo «Objeto» es de Tipo «? se extiende el Objeto». Así que usted no puede pasar la declaró «Objeto» de tipo. Usted no puede pasar cualquier cosa en todos.

Así que al final termina declarando agradable interfaces que, como resulta, no se pueden crear instancias de la derecha.

¿Tienes ideas de cómo modelar un caso de uso, donde las subclases tendrán que sustituir el tipo de retorno, mientras que el tipo de retorno es una de genéricos?

O cómo ir alrededor de un modelo de caso?

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

———– (1) edición debido a las respuestas ———–

Una muy buena idea básica es que la interfaz sea más abstracta! Yo tenía exactamente la misma idea de la primera, pero… (esto tiene que venir)

Asumir haciendo esto:

Se introduce una nueva interfaz de AGeneric

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

Ahora vamos a tener que ampliar a y A1 de esta nueva interfaz:

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

Que funciona bien, a pesar de que se rompe la ruta de acceso de la herencia original.

Si queremos A1 todavía ser extensible a partir de Una, tenemos que cambiar de A1 a

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

y hay un problema de nuevo. Esto no funciona, ya que ampliamos indirectamente la misma interfaz con diferentes tipos genéricos. Esto, desafortunadamente, no es permitido.

Ves el problema?

Y a punto para otra circunstancia:

Si lanzas la GenericType<? extends Object> a GenericType<Object> obviamente obras.
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 que parece para mí que la resolución de que el tipo de parámetro del método

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

está mal.

Si D es unificado con «? se extiende el Objeto» ¿por qué el tipo de parámetro no está obligado a ser «Objeto»?

Wouldnt esto hacer más sence?

Lo siento, pero estoy dispuesto a leer a través de 5 páginas para entender su pregunta. Le recomiendo que pregunte en una forma más compacta en el futuro. Usted todavía puede explicar que las soluciones que ya se han probado, pero por favor, por lo que después le ha pedido a su pregunta, así que los que ya saben la respuesta puede responder de inmediato.
Entiendo que la introducción no es el más corto. Pero a ver, yo tenía una pregunta para el modelo de caso. ¿Cómo debo preguntar sin, al menos, demostrar que el modelo de caso antes? Si me puede dar una pista de cómo lograr esto, me encantaría acortar el texto!
Recuerdo un caso en el Guayaba biblioteca, donde exactamente su problema ocurrido. El Multimap interfaz declara Map<K,Collection<V>> asMap(). La sub interfaz SetMultimap no puede cambiar los genéricos del tipo de retorno de Collection<V> a Set<V>, y por lo tanto, la siguiente documentación se añadió: «a Pesar de la firma del método no lo dice explícitamente, que devuelve el mapa ha Set valores».
usuario: comienza con una lista completa de sus necesidades. Por ejemplo, los 9 primeros párrafos puede ser reducido a: «Cuando se reemplaza un método, puede que se especializan en un tipo de parámetro que aparece en un tipo de retorno?» . A continuación, puede seguir con un ejemplo. Coloridos ejemplos de ayuda, así por ejemplo: interface Habitat { List<Animal> getOccupants();} interface FishTank extends Habitat { List<Fish> getOccupants();} … y ya hemos cubierto el próximo 4 párrafos.

OriginalEl autor Omnaest | 2011-02-20

6 Comentarios

  1. 6

    Una idea básica es ahora para cambiar esta genérica tipo de retorno de GenericType en Una Interfaz en GenericType en la Interfaz A1

    Esto no es posible, porque Java Genéricos son invariantes. [1]

    Como usted que se encuentra fuera, usted no puede tener una interfaz de declarar un método que devuelve GenericType<Object> y en un sub interfaz de reemplazar el método para devolver GenericType<String>: El último tipo de retorno no es un subtipo de la antigua. Y por una buena razón!

    Intentó

    extender de forma indirecta la misma interfaz con diferentes tipos genéricos. Esto, desafortunadamente, no es permitido.

    No hay manera de que esto podría funcionar: E. g. ¿cuál debe ser el tipo de E en public E set(int index, E element) en una clase que implementa tanto List<String> y List<Object>? Su subclases de la interfaz tendría que producir un híbrido similar: El valor de retorno de getAGenericType en la sub interfaz tendría que poner en práctica tanto la GenericType<String> y la GenericType<Object> de la interfaz. Y como hemos visto, esto es imposible.

    El compilador no sabe qué va a hacer con el parámetro de tipo en GenericType (a pesar de que, teóricamente, podría averiguar, no). Si había una variable de tipo GenericType<String> y se le asigna un GenericType<Object>, puede muy bien terminar poniendo un Long instancia en la que un String que se espera, y obtener un ClassCastException donde no esperar.

    En el doSomethingWith método de la variable GenericType<? extends Object> aGenericType2 usted puede pasar una cosa: null. null es el único objeto de referencia que tiene un subtipo de ? extends Object. El límite inferior del tipo de ? extends Object es el null tipo, que no puede ser expresado en Java, y sólo implícitamente existe, como el tipo de la null de referencia.

    [1] http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Java

    Youre derecho límite inferior sería nulo de tipo, a lo que me refería era el «Objeto» de la frontera. ¿Por qué no es utilizado como el tipo de parámetro?
    El tipo de parámetro de método doSomethingWith en GenericType<? extends Object> aGenericType2 es ? extends Object, debido a que el método se ha declarado: Su parámetro tiene como tipo el tipo de parámetro de la clase (nombre D en su declaración). Sólo puede pasar argumentos cuyo tipo es un subtipo del tipo de parámetro. Y Object no es subtipo de ese tipo. El método no se limita a «tomar un argumento de cualquier subtipo de Objeto», pero sí «toma un argumento de un fijo, pero no se especifica, el subtipo de Objeto».
    Gracias por la aclaración! Para terminar, que la única «buena» manera de hacer las cosas aquí, es dejar que los tipos de devolución como son y se lanzó a lo que se necesita para.
    Sí, tienes razón en eso. Hay algunas constelaciones, donde se debe preferir una solución sencilla a través de una compilación de tiempo verificables solución. Desde Java genéricos no permitir que lo que usted necesita, documento de la intención de comportamiento del tiempo de ejecución y los tipos, y el uso de moldes.

    OriginalEl autor Christian Semrau

  2. 2

    @Override anotación:

    Cuando se reemplaza un método, usted puede
    desea utilizar el @Override anotación
    que indica al compilador que
    la intención de sustituir un método en el
    superclase. Si, por alguna razón, la
    compilador detecta que el método no
    no existe en una de las superclases,
    se generará un error.

    Con esta anotación no puede cambiar el tipo de retorno de la función.

    Si desea reemplazar el tipo de devolución, acaba de hacer Una interfaz más abstracto, agregar genérico para esta interfaz:

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

    La muestra acerca de cómo reemplazar a un método genérico de una clase genérica.

    Gracias por tu respuesta! Con la anotación creo que su tipo de mal. Su supuesto posible reemplazar el tipo de retorno. Por otro lado la idea de que con el más abstracto de la clase me parece muy bueno para mí, incluso si se lleva a otro problema. He editado la pregunta original de texto para mostrar los detalles para que!
    ahora el problema está en la división de interfaces, tratar de ser un modelo de arquitectura (puede ser en papel), puede ser que no hay necesidad de heredan de la interfaz de A1 a partir de Una?
    Que como no esta permitido heredar Superdeportivo de Coche sólo porque los cables tienen diferentes tipos. No sé si el papel es el problema aquí.
    «Con esta anotación no puede cambiar el tipo de retorno de la función.» es incorrecta, Java ha covariante tipos de retorno desde Java 5, es decir, un método para reemplazar a otro puede devolver un subtipo de el método del tipo de retorno.
    «Que como no esta permitido heredar Superdeportivo de Coche sólo porque los cables tienen diferentes tipos.» Bueno, sí! Si un Superdeportivo permite el uso de cables que un Coche iba a rechazar, o si Superdeportivo sería no permitir un tipo de cable que un Coche iba a permitir, entonces Superdeportivo no puede heredar de Coche.

    OriginalEl autor Sergey Vedernikov

  3. 2

    No sé si esto es lo que están esperando, pero Usted puede declarar su interfaz algo como esto

    public interface Interface <K extends Object> { ... }    

    Mientras la clase podría parecer

    public class InterfaceImpl extends Interface<String> { ... }

    OriginalEl autor Mihir

  4. 1

    El problema es que InterfaceA no sabe de qué tipo es la celebración. Si usted consigue InterfaceA a tomar un genérico argumento, entonces usted podría hacer esto:

    public interface InterfaceA<T>
    {
      public GenericType<T> getAGenericType();  
    }
    
    public interface InterfaceA1 extends InterfaceA<String>
    {
      @Override
      public GenericType<String> getAGenericType();
    }
    
    public class LookAtTheInstance
    {
      @SuppressWarnings("null")
      public static void method()
      {
        InterfaceA<String> a = null;
        InterfaceA1 a1 = null;
    
        GenericType<String> aGenericType = a1.getAGenericType();
    
        GenericType<String> aGenericType2 = a.getAGenericType();
        String something = null;
        aGenericType2.doSomethingWith( something );
      }
    }
    Sí eso es mi primera idea, también. Y pensé que sería genial, pero… los detalles en el post original en el «editar» de la sección! Se supone que usted ha leído la edición del post, ¿qué piensa usted sobre el problema?

    OriginalEl autor SimonC

  5. 1

    Estoy varios años tarde a la fiesta, pero he encontrado esta página mientras buscaba una pregunta relacionada y ninguna de las respuestas realmente golpeó en el centro de la cuestión, que creo que es la pena aclarar. Veamos un poco más de la pulpa de la salida ejemplo:

    Conceptualmente, GenericType NO es un GenericType, desde un GenericType sólo puede doSomethingWith() Cuerdas, mientras que una GenericType necesita ser capaz de doSomethingWith() de cualquier objeto. GenericType es un compromiso que el compilador le permite su uso como una «clase base» para cualquier GenericType donde D es-un Objeto, pero sólo permite el uso de una referencia de ese tipo para llamar a métodos que son de tipo seguro para cualquier posible valor de tiempo de ejecución de ‘?’ (como getAValue(), cuyo valor de retorno puede ser siempre de forma segura echado a un Objeto puesto que D es-un Objeto independientemente de su tipo en tiempo de ejecución).

    Es difícil decir lo que (si acaso) el cartel original era en realidad tratando de modelo con este código, y, en particular, cuánto genérico-ness de GenericType era realmente necesario, pero tal vez la herencia debería haber sido al revés?

    La desventaja es que no hay buena manera de expresar el compilador de java que NonGenericType se extiende GenericType, aunque conceptualmente se podría en este caso, ya que GenericType nunca utiliza el D como valor de retorno. Usted tiene que especificar manualmente cada GenericType que desea ampliar. 🙁

    OriginalEl autor David

  6. 0

    Así que al final termina declarando agradable interfaces que, como resulta, no se pueden crear instancias de la derecha.

    Creo que el propósito de InterfaceA no es ser instanciado en todo, porque uno de sus confiable clases son de carácter genérico. Eso es lo que significaba declarar:

    Sí, y yo no quiero que parezca que. Lo que yo quiero es simplemente ‘GenericType<Objeto>’. Eso es exactamente el punto. Pero, ¿cómo llegar?

    OriginalEl autor yegor256

Dejar respuesta

Please enter your comment!
Please enter your name here