9

这是受保护方法的文档:

/** 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;

    }
}
4

2 回答 2

18

(编辑:theycallmemorty 的回答给出了在你的情况下避免这个问题的实用建议。这个答案给出了为什么你必须遵循这个建议的原因,即为什么语言是这样设计的。)

您只能访问与访问代码(或子类)具有相同类型的另一个对象的受保护成员 - 即使该成员是在超类型中声明的。

来自Java 语言规范,第 6.6.2 节

令 C 为声明受保护成员 m 的类。仅允许在 C 的子类 S 的主体内进行访问。此外,如果 Id 表示实例字段或实例方法,则:

  • 如果通过限定名称 Q.Id 进行访问,其中 Q 是 ExpressionName,则当且仅当表达式 Q 的类型是 S 或 S 的子类时才允许访问。
  • 如果通过字段访问表达式 E.Id(其中 E 是 Primary 表达式)或通过方法调用表达式 E.Id(. . .)(其中 E 是 Primary 表达式)进行访问,则当且仅如果 E 的类型是 S 或 S 的子类。

这是为了允许一个类型访问与其自己的继承树相关的成员,而不会破坏其他类的封装。例如,假设我们有:

     A
    / \
   B   Other
  /
 C

和 A 声明一个受保护的成员x。如果规则没有按照它的方式工作,您可以通过将成员放入来获得圆形封装Other

public int getX(A a)
{
    return a.x;
}

B并且只是在or的实例中调用它C- 成员将有效地公开,因为您总是可以通过引入另一个类来解决它......这不是一个好主意。使用当前规则,您必须继承BC- 您可能一开始就无法做到这一点。

于 2009-10-25T21:57:07.803 回答
15

通过做这个:

MidiSynth synth = new MidiSynth();
sequence = synth.scoreToSeq(score); 

您实际上并没有利用您已经扩展了 MidiSynth 类的事实。

如果你想尝试

this.scoreToSec(score);

然后你会发现你可以访问受保护的功能。

于 2009-10-25T21:58:26.897 回答