Domanda
Ho appena ricevuto un errore strano che coinvolge modificatore protetto.
Ho il codice seguente:
package p1;
public class C1 {
protected void doIt() {}
}
package p2;
public class C2 extends p1.C1 {
private C1 c1_instance;
public void doItAgain() {
c1_instance.doIt(); // wtf!!!!
}
}
Ricevo errori, affermandolo doIt()
ha accesso protetto e non può accedere! Ma sono in sottoclasse e ho e accesso a doIt()
metodo.
Non è un bug?
Soluzione
Ho anche avuto l'impressione di cosa protected
significava "accessibile dallo stesso pacchetto o da una sottoclasse" ma il Specifica del linguaggio Java è ovviamente più preciso e spiega che in una sottoclasse S di C, "Se l'accesso è con un nome qualificato Q.id, dove Q è un nome di espressione, l'accesso è consentito se e solo se il tipo di espressione Q è S o una sottoclasse di S. "
Quindi puoi accedere solo a protected
Metodo della superclasse tramite un riferimento alla sottoclasse da cui stai chiamando, in questo modo:
public class C2 extends C1 {
private C2 c2_other_instance;
public void doItAgain() {
c2_other_instance.doIt();
}
}
Se spieghi perché vuoi accedere a un'istanza della superclasse da un'istanza diversa della sottoclasse, qualcuno potrebbe essere in grado di suggerire un design migliore. Altrimenti dovrai creare il metodo public
o mettere le classi nello stesso pacchetto.
Altri suggerimenti
In Java, non puoi chiamare protected
metodi su un esempio diverso della classe base, anche dall'interno di una sottoclasse:
public class C2 extends p1.C1 {
private C1 c1_instance;
public void doItAgain() {
doIt(); // fine
c1_instance.doIt(); // disallowed
}
}
L'unica eccezione è quando sia la classe base che la sottoclasse sono nello stesso pacchetto.
Per citare il Tutorial Java oo:
Il
protected
Il modificatore specifica che è possibile accedere al membro solo all'interno del proprio pacchetto (come con il pacchetto-privato) e, inoltre, da una sottoclasse della sua classe in un altro pacchetto.
Protetto è equivalente all'accesso a livello di pacchetto; Non puoi accedere al metodo se sei in un pacchetto diverso.
Dovresti essere in grado di chiamare Doit () direttamente senza passare attraverso l'oggetto C1_Instance, poiché C2 è una sottoclasse.
Da http://download.oracle.com/javase/tutorial/java/javaoo/accesscontrol.html
"Il modificatore protetto specifica che al membro è possibile accedere solo all'interno del proprio pacchetto (come con il pacchetto-privato) e, inoltre, da una sottoclasse della sua classe in un altro pacchetto."
C2 può essere una sottoblaction di C1, ma ciò non significa che possa accedere a tali metodi su un'istanza diversa, cioè C1_instance potrebbe non essere un'istanza di C2. Potresti accedervi se fosse nello stesso pacchetto.
No, protected
Assicura l'accesso nello stesso pacchetto e nelle classi discendenti. Non sei né nello stesso pacchetto né lo stai accedendo direttamente da una classe discendente. C2
è un discendente ma c1_instance
non è.
Se il tuo metodo è dichiarato protetto, puoi accedervi all'interno di questa classe, con il pacchetto e all'interno della sottoclasse.
Ora ecco la domanda, perché c'è un errore nonostante l'accesso a questo membro protetto dalla sua sottoclasse. La risposta è accedere al metodo protetto da una sottoclasse che la sottoclasse dovrebbe utilizzare il metodo direttamente dalla sottoclasse diretta. Qui la sottoclasse diretta è C2 ma l'istanza C1_Instance non lo è. È possibile utilizzare questo metodo direttamente (doit () al posto di c1_instance.doit ())