pourquoi ne puis-je pas accéder à la méthode Java protégée même si j'ai étendu la classe?
-
06-07-2019 - |
Question
Voici la documentation de la méthode protégée:
/** Converts jmusic score data into a MIDI Sequence */
protected javax.sound.midi.Sequence scoreToSeq(Score score)
Et j'ai créé cette petite classe pour étendre celle de la méthode 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;
}
}
La solution
(EDIT: Theycallmemorty answer vous donne des conseils pratiques pour éviter ce problème dans votre cas. Cette réponse explique les raisons pour lesquelles vous devez suivre ces conseils, c.-à-d. Pourquoi le langage a été conçu de cette manière.)
Vous pouvez uniquement accéder à un membre protégé d'un autre objet du même type que le code d'accès (ou une sous-classe), même si le membre est déclaré dans un supertype.
Extrait de la Spécification du langage Java, section 6.6.2 :
Soit C la classe dans laquelle a membre protégé m est déclaré. Accès est autorisé uniquement dans le corps d'un sous-classe S de C. En outre, si Id dénote un champ ou une instance méthode, puis:
- Si l'accès se fait par un nom qualifié Q.Id, où Q est un nom d'expression, alors l'accès est autorisé si et seulement si le type de l'expression Q est S ou une sous-classe de S.
- Si l'accès se fait par une expression d'accès au champ E.Id, où E est un primaire expression, ou par une invocation de méthode expression E.Id (...), où E est un Expression primaire, alors l'accès est permis si et seulement si le type de E est S ou une sous-classe de S.
Ceci permet à un type d'accéder aux membres pertinents pour son propre arbre d'héritage, sans compromettre l'encapsulation d'autres classes. Par exemple, supposons que nous ayons:
A
/ \
B Other
/
C
et A ont déclaré un membre protégé x
. Si la règle ne fonctionne pas comme elle le fait, vous pouvez contourner l’encapsulation en plaçant un membre dans Autre
:
public int getX(A a)
{
return a.x;
}
et en appelant simplement cela en passant une instance de B
ou C
- le membre deviendrait effectivement public, car vous pourriez toujours le contourner en introduisant une autre classe. . pas une bonne idée. Avec la règle actuelle, vous devez sous-classer B
ou C
- ce que vous ne pourrez peut-être pas en premier lieu.
Autres conseils
En procédant ainsi:
MidiSynth synth = new MidiSynth();
sequence = synth.scoreToSeq(score);
Vous ne tirez pas parti du fait que vous avez étendu la classe MidiSynth.
Si vous deviez essayer
this.scoreToSec(score);
Vous constaterez alors que vous avez accès à la fonction protégée.