2016-03-24 8 views
5

Sto chiamando un metodo protetto di super classe da una sottoclasse. Perché questo metodo "non è visibile"?Java: chiamando un metodo protetto di super classe da una sottoclasse - non visibile?

Ho letto alcuni messaggi, come this one, che sembrano contraddire la seguente:

classe Super:

package com.first; 

public class Base 
{ 
    protected void sayHello() 
    { 
     System.out.println("hi!"); 
    } 
} 

sottoclasse:

package com.second; 

import com.first.Base; 

public class BaseChild extends Base 
{ 
    Base base = new Base(); 

    @Override 
    protected void sayHello() 
    { 
     super.sayHello(); //OK :) 
     base.sayHello(); //Hmmm... "The method sayHello() from the type Base is not visible" ?!? 
    } 
} 
+4

Ma si estende Base – rapt

+0

http://stackoverflow.com/a/19949354/868975 – Bax

+0

Stesso come forse questo uno: http://stackoverflow.com/questions/36093187/accessing-protected-member-of-static- class-in-subclass-of-the-parent # comment59830891_36093187 – aioobe

risposta

9

base è una variabile che non è speciale in alcun modo: non fa parte di una gerarchia di classi e l'accesso protetto non è disponibile attraverso di esso. Anche se sayHello ha accesso ai membri protetti di Base, ha quell'accesso solo tramite ereditarietà (poiché non è nello stesso pacchetto: la parola chiave protected consente l'accesso tramite ereditarietà e pacchetto, vedere la tabella in this Oracle tutorial).

L'accesso tramite this e super è consentito perché fanno parte della gerarchia di ereditarietà.

+3

Penso che tu sia l'unico qui che ha notato che 'base' era solo una variabile. –

+2

Penso di aver bisogno di una terminologia migliore. So cosa sto cercando di dire, ma penso che ci siano termini meglio accettati che non posso attualmente ricordare .. –

+0

Questo è ancora sorprendente, dal momento che è possibile chiamare metodi privati ​​su qualsiasi istanza della classe attualmente dichiarata ('this' e qualsiasi istanza diversa da' this'). Il seguente codice funziona: 'public class A {private void b() {new A(). B(); }} ' –

-3

Il tastiera protetta è per visibilità sullo stesso pacchetto. Se la classe figlia non è dello stesso pacchetto, i metodi protetti di genitore non sono visibili alla classe figlia.

+4

Assolutamente sbagliato. – Bax

+1

Spero che i voti positivi qui siano solo per simpatia ... – ChiefTwoPencils

3

Questo è il comportamento corretto. Infatti, Java Language Specification, sezione, 6.6.2-1, ha un esempio molto simile al tuo, con un commento che non dovrebbe essere compilato.

Le specifiche di accesso ai membri protetti sono descritti nella sezione 6.6.2.1:

6.6.2.1. Accesso a un membro protetto

Lascia che sia C la classe in cui è dichiarato un membro protetto. L'accesso è consentito solo all'interno del corpo di una sottoclasse S di C.

Inoltre, se Id indicato un campo di istanza o un metodo esempio, allora:

Se l'accesso è da un nome qualificato Q.Id, dove Q è un ExpressionName, quindi l'accesso è consentito se e solo se il tipo dell'espressione Q è S o una sottoclasse di S.

Se l'accesso è da un accesso campo di espressione E.Id, dove E è un'espressione primaria, o con una chiamata di metodo espressione E.Id(. . .), dove E è un'espressione primaria, quindi l'accesso è consentito se e solo se il tipo di E è S o una sottoclasse di S.

È l'ultimo paragrafo che descrive il motivo per cui l'accesso deve essere negato.Nel tuo esempio, C è Base, S è BaseChild e E, il tipo di variabile base, è anche Base. Poiché Base non è né un BaseChild né una sottoclasse di BaseChild, l'accesso è negato.

+0

Mentre capisco che questo impedisce l'accesso tramite 'base', non vedo come possa accedere tramite' super'. Non è 'super' dello stesso tipo di' base'? Forse mi sono perso qualcosa nel JLS? È permesso in un'altra parte del JLS? Non sono riuscito a trovare una sezione che lo consenta. –

+1

@StefanDollase Questa è la cosa, 'super' non è un campo, è una parola chiave che ti consente di accedere ai metodi della classe base sovrascritti nella tua classe. Tuttavia, il riferimento effettivo viene fatto tramite 'this', non attraverso una variabile diversa. – dasblinkenlight

Problemi correlati