perché non riesco ad accedere al metodo java protetto anche se ho esteso la classe?
-
06-07-2019 - |
Domanda
Ecco la documentazione per il metodo protetto:
/** Converts jmusic score data into a MIDI Sequence */
protected javax.sound.midi.Sequence scoreToSeq(Score score)
E ho creato questa piccola classe per estendere la classe da cui proviene il metodo scoreToSeq:
public class MidiSequence extends MidiSynth{
public Sequence getSequence(Score score){
MidiSynth synth = new MidiSynth();
Sequence sequence = null;
try
{
// Here I get the error saying that the method has
// protected access in MidiSynth
sequence = synth.scoreToSeq(score);
}
catch (InvalidMidiDataException e)
{
/*
* In case of an exception, we dump the exception
* including the stack trace to the console.
* Then, we exit the program.
*/
e.printStackTrace();
System.exit(1);
}
return sequence;
}
}
Soluzione
(EDIT: risposta di theycallmemorty fornisce consigli pratici per evitare questo problema nel tuo caso. Questa risposta fornisce i motivi per cui devi seguire quel consiglio, ovvero perché la lingua è stata progettata in questo modo.)
Puoi accedere solo a un membro protetto di un altro oggetto dello stesso tipo del codice di accesso (o di una sottoclasse), anche se il membro è dichiarato in un supertipo.
Dalla Specifica della lingua Java, sezione 6.6.2 :
Sia C la classe in cui a viene dichiarato il membro protetto m. Accesso è consentito solo all'interno del corpo di a sottoclasse S di C. Inoltre, se Id indica un campo o un'istanza dell'istanza metodo, quindi:
- Se l'accesso avviene con 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 avviene tramite un'espressione di accesso al campo E.Id, dove E è un primario espressione o mediante una chiamata al metodo espressione E.Id (...), dove E è a Espressione primaria, quindi l'accesso è consentito se e solo se il tipo di E è S o una sottoclasse di S.
Questo per consentire a un tipo di accedere ai membri rilevanti per il proprio albero ereditario, senza sconfiggere l'incapsulamento di altre classi. Ad esempio, supponiamo di avere:
A
/ \
B Other
/
C
e A hanno dichiarato un membro protetto x
. Senza che la regola funzioni nel modo in cui funziona, potresti ottenere l'incapsulamento circolare inserendo un membro in Altro
:
public int getX(A a)
{
return a.x;
}
e chiamandolo semplicemente passando in un'istanza di B
o C
- il membro diventerebbe effettivamente pubblico, perché potresti sempre aggirare il problema introducendo un'altra classe .. . non è una buona idea. Con la regola attuale, dovresti sottoclassare B
o C
- cosa che potresti non essere in grado di fare in primo luogo.
Altri suggerimenti
In questo modo:
MidiSynth synth = new MidiSynth();
sequence = synth.scoreToSeq(score);
In realtà non stai sfruttando il fatto che hai esteso la classe MidiSynth.
Se dovessi provare
this.scoreToSec(score);
Quindi scoprirai di avere accesso alla funzione protetta.