Métodos e interfaces predeterminados que amplían otras interfaces


Supongamos que hay dos interfaces Interface1 y Interface2 donde Interface2 se extiende Interface1.

interface Interface1 {

    default void method() {
        System.out.println("1");
    }

    // Other methods
}

interface Interface2 extends Interface1 {

    @Override
    default void method() {
        System.out.println("2");
    }

    // Other methods
}

Supongamos que quiero crear una clase que implemente Interface2 pero quiero que method() sea la versión en Interface1. Si escribo

class MyClass implements Interface1, Interface2 {

    public void method() {
        Interface1.super.method();
    }
}

Recibo el error de compilación:

Mal calificador de tipo por defecto super llamada: interfaz redundante Interface1 se extiende por Interface2

Es posible sortear esto creando un tercero interfaz:

interface Interface3 extends Interface1 {

    default void method() {
        Interface1.super.method();
    }
}

Entonces:

class MyClass implements Interface1, Interface2, Interface3 {

    public void method() {
        Interface3.super.method();
    }
}

Esto compila bien, y si instancio un nuevo MyClass e invoco method(), la salida es 1 como se esperaba.

Así que mi pregunta es, dado que es tan fácil sortear la restricción que solo se puede escribir InterfaceName.super.method() para la interfaz más específica de una cadena, ¿cuál es la razón de la restricción? ¿Qué problemas se evitan al no permitirle escribir Interface1.super.method() en primer lugar?

Author: Radiodef, 2015-04-09

1 answers

Esto es exactamente abordado por la JLS en 15.12.3. "Paso 3: ¿Es Apropiado el Método Elegido?".

Si la forma es TypeName . super . [TypeArguments] Identificador , luego:

  • […]
  • Si TypeName denota una interfaz, sea T la declaración de tipo que encierra inmediatamente la invocación del método. Se produce un error en tiempo de compilación si existe un método, distinto del tiempo de compilación declaración, que anula (§9.4.1) la declaración en tiempo de compilación de una superclase directa o superinterface directa de T.

La JLS continúa explicando por qué la regla está en su lugar:

En el caso de que una superinterface anule un método declarado en una interfaz de abuelos, esta regla impide que la interfaz hija "omita" la anulación simplemente agregando el abuelo a su lista de superinterfaces directas. El la forma apropiada de acceder a la funcionalidad de un abuelo es a través de la superinterface directa, y solo si esa interfaz elige exponer el comportamiento deseado.

Así que más o menos existe específicamente para evitar que hagas lo que estás tratando de hacer.

Pero la JLS también parece reconocer su solución alternativa:

(Alternativamente, el desarrollador es libre de definir su propia superinterface adicional que expone el comportamiento deseado con un método super invocación.)

 17
Author: Radiodef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-09 08:19:44