以下是受保护方法的文档:
/** Converts jmusic score data into a MIDI Sequence */
protected javax.sound.midi.Sequence scoreToSeq(Score score)
我创建了这个小课程来扩展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;
}
}
答案 0 :(得分:17)
(编辑:theycallmemorty's answer给出了在你的案例中避免这个问题的实用建议。这个答案给出了为什么你必须遵循这个建议的原因,即为什么语言是这样设计的。)
您只能访问与访问代码(或子类)类型相同的另一个对象的受保护成员 - 即使该成员在超类型中声明。
来自Java Language Specification, section 6.6.2:
让C成为a的类 保护成员m被声明。访问 只允许在一个体内 C的子类S.此外,如果Id 表示实例字段或实例 方法,然后:
- 如果访问是通过限定名称Q.Id,其中Q是ExpressionName, 然后,如果和,则允许访问 只有表达式Q的类型 是S或S的子类。
- 如果访问是通过字段访问表达式E.Id,其中E是主要 表达式,或通过方法调用 表达式E.Id(...),其中E是a 主要表达,然后访问是 当且仅当E的类型允许 是S或S的子类。
这是为了允许类型访问与其自己的继承树相关的成员,而不会破坏其他类的封装。例如,假设我们有:
A
/ \
B Other
/
C
和A声明受保护的成员x
。如果没有规则按照它的方式工作,你可以通过在Other
中添加一个成员来实现封装:
public int getX(A a)
{
return a.x;
}
并且只是调用传递B
或C
的实例 - 该成员将有效地公开,因为您可以通过引入另一个类来解决它...不是一个好主意。使用当前规则,您必须创建子类B
或C
- 您可能无法将其置于最初。
答案 1 :(得分:12)
通过这样做:
MidiSynth synth = new MidiSynth();
sequence = synth.scoreToSeq(score);
你实际上没有利用你扩展MidiSynth类的事实。
如果你要尝试
this.scoreToSec(score);
然后你会发现你可以访问受保护的功能。