¿Por qué no puedo reemplazar el método mediante la implementación de la clase como parámetro

severa:

Tengo estructura abstracta sencilla

public abstract class Data<A extends Serializable> {

}

y luego puesta en práctica de esta clase de cuerdas

public class StringData extends Data<String> {

}

entonces tengo Interfaz:

public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}

y ahora quiero crear clases que implementan esta interfaz:

public class TesticekImpl implements Testicek<String> {


    // OK
    @Override
    public StringData test(Data<String> bla) {
        return null;
    }

    // compilation error
    //@Override
    //public StringData test(StringData bla) {
    //    return null;
    //}

}

¿Por qué no puedo usar mi clase StringData como parámetro y sólo funciona en el tipo de cambio? Firmas de tipo de retorno y el parámetro son los mismos.

Andy Turner:
public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}

Java permite tipos de retorno covariantes , lo que significa que las implementaciones de una interfaz puede volver tipos más específicos de la interfaz de los padres, porque esos tipos más específicos son todavía menos instancias de tipos específicos, y por lo tanto cumple con el contrato de la interfaz.

Sin embargo, no se puede usar más tipos de parámetros específicos, ya que el contrato de la interfaz dice que debe aceptar cualquier instancia de ese tipo.

El principio de sustitución de liskov nos dice que las subclases tienen que aceptar los parámetros que no más son restrictivas, y deben devolver valores que no más son generales.

Java no permite utilizar los tipos de parámetros "menos restrictivas", debido a la forma en que se resuelve para invocar métodos en tiempo de compilación (que ya está bastante complicado). Esto es innecesariamente restrictivo desde un punto de vista teórico, pero más simple desde un punto de vista práctico.

En términos de que aceptar y devolver el mismo tipo: declarar otra variable de tipo en su interfaz:

public interface Testicek<A extends Serializable, D extends Data<A>> {

    public abstract D test(D bla);

}

A continuación, su aplicación puede ser:

public class TesticekImpl implements Testicek<String, StringData> {
    @Override
    public StringData test(StringData bla) {
        return null;
    }
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=185997&siteId=1
Recomendado
Clasificación