¿Por qué no puedo acceder al método Java protegido aunque haya ampliado la clase?
-
06-07-2019 - |
Pregunta
Aquí está la documentación para el método protegido:
/** Converts jmusic score data into a MIDI Sequence */
protected javax.sound.midi.Sequence scoreToSeq(Score score)
E hice esta pequeña clase para extender la clase de la que proviene el método 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;
}
}
Solución
(EDITAR: la respuesta de theycallmemorty brinda consejos prácticos para evitar este problema en su caso. Esta respuesta brinda los motivos por los que debe seguir ese consejo, es decir, por qué el lenguaje se ha diseñado de esa manera.)
Solo puede acceder a un miembro protegido de otro objeto que sea del mismo tipo que el código de acceso (o una subclase), aunque el miembro esté declarado en un supertipo.
De la sección Java Language Specification, sección 6.6.2 :
Sea C la clase en la que un se declara miembro protegido m. Acceso está permitido solo dentro del cuerpo de un subclase S de C. Además, si Id denota un campo de instancia o instancia método, entonces:
- Si el acceso es por un nombre calificado Q.Id, donde Q es un ExpressionName, entonces el acceso está permitido si y solo si el tipo de la expresión Q es S o una subclase de S.
- Si el acceso es por una expresión de acceso de campo E.Id, donde E es un primario expresión, o mediante una invocación de método expresión E.Id (...), donde E es un Expresión primaria, entonces el acceso es permitido si y solo si el tipo de E es S o una subclase de S.
Esto es para permitir que un tipo acceda a miembros relevantes para su propio árbol de herencia, sin derrotar la encapsulación de otras clases. Por ejemplo, supongamos que tenemos:
A
/ \
B Other
/
C
y A declararon un miembro protegido x
. Sin que la regla funcione como lo hace, puede obtener una encapsulación redonda colocando un miembro en Other
:
public int getX(A a)
{
return a.x;
}
y simplemente llamando a eso pasar en una instancia de B
o C
: el miembro se volvería público de manera efectiva, porque siempre podría solucionarlo introduciendo otra clase. . no es Buena idea. Con la regla actual, tendrías que subclasificar B
o C
, lo que puede que no puedas hacer en primer lugar.
Otros consejos
Al hacer esto:
MidiSynth synth = new MidiSynth();
sequence = synth.scoreToSeq(score);
No estás aprovechando el hecho de que has extendido la clase MidiSynth.
Si tuviera que intentarlo
this.scoreToSec(score);
Entonces verás que tienes acceso a la función protegida.