Perché la classe interna deve specificare Outer.this.remove (int)? [chiuso]

0

Perché una classe interna qualche volta deve specificare esplicitamente l'istanza della classe esterna per chiamare un metodo di classe esterno per il quale non esiste un metodo di matching nella classe interna?

Esempio:

import java.util.Iterator;

public class Outer {
    void remove(int index) {}

    private class Inner implements Iterator {
        @Override
        public boolean hasNext() {
            return false;
        }

        @Override
        public Object next() {
            return null;
        }

        @Override
        public void remove() {
            remove(0); // error: remove() in Inner cannot be applied to (int)
            Outer.this.remove(0); // ok
        }
    }
}

Il mio tentativo originale non riuscito in un esempio mostra che questa disambiguazione è non generalmente richiesta:

public class Outer {
  private Object field;

  void method() {}

  private class Inner {
    void innerMethod() {
      if(field == null) {
        method(); // ok
        Outer.this.method(); // ok
      }
    }
  }
}
    
posta Kevin Krumwiede 17.12.2015 - 18:18
fonte

2 risposte

3

L'intera premessa della domanda è sbagliata. Se rimuovi Outer.this , verrà compilato normalmente. Non è necessario qualificare l'accesso al metodo se non vi è ambiguità. La domanda che hai collegato ha chiesto specificamente cosa fare se sia la classe interna che quella esterna hanno un metodo con la stessa firma e come decidere quale metodo chiamare (poi restituisce l'interno per impostazione predefinita, esterno per qualifica esplicita)

    
risposta data 17.12.2015 - 19:35
fonte
3

Questa è un'opinione piuttosto che una risposta, poiché non lo sono e non ho fatto parte del team di sviluppo Java. Ma un parere con riferimenti JLS.

Penso che sia un incidente, causato da una specifica inutilmente troppo precisa. In altre parole, un de facto bug ma de jure comportamento previsto.

Le specifiche in questione sono JLS 15.12 , Espressioni di richiamo del metodo , e in particolare JLS 15.12.1 , Compile-Time Passaggio 1: determina la classe o l'interfaccia per la ricerca :

The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to search for definitions of methods of that name.

Nota che le specifiche usano il termine "nome" piuttosto che "firma".

If the Identifier appears in the scope of a visible method declaration with that name (§6.3, §6.4.1), then: If there is an enclosing type declaration of which that method is a member, let T be the innermost such type declaration. The class or interface to search is T.

Notare la terminologia "più interna di tale dichiarazione di tipo". Mentre leggo questo, una volta che il tipo di dichiarazione è stato selezionato, allora è il tipo solo che verrà cercato per i metodi del nome specificato.

Quindi, per applicare questo:

  • Nell'esempio originale, hai usato due nomi diversi. Il compilatore ha identificato che il nome era stato dichiarato nella classe che lo includeva e non c'era bisogno di usare la disambiguazione.
  • Nell'esempio collegato, le firme del metodo sono le stesse. Ciò richiederebbe una disambiguazione anche se le specifiche fossero diverse.
  • Nell'esempio finale, il metodo nome appare nella classe interna, quindi il compilatore guarda a quella classe per la risoluzione. Tuttavia, poiché la classe interna non definisce la firma corretta, non è in grado di risolvere il metodo senza disambiguazione.

Quindi, hai un comportamento. Per quanto riguarda la ragione, a meno che @BrianGoetz o un'altra persona con conoscenza personale decida di rispondere, dovremo solo speculare.

    
risposta data 18.12.2015 - 13:01
fonte

Leggi altre domande sui tag