почему я не могу получить доступ к защищенному методу Java даже при мысли, что расширил класс? - PullRequest
8 голосов
/ 26 октября 2009

Вот документация для защищенного метода:

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

    }
}

Ответы [ 2 ]

17 голосов
/ 26 октября 2009

(РЕДАКТИРОВАТЬ: ответ они непременно дает практический совет, как избежать этой проблемы в вашем случае. В этом ответе приведены причины, по которым вы должны следовать этому совету, т. Е. Почему язык был разработан таким образом. )

Вы можете получить доступ только к защищенному члену другого объекта того же типа, что и код доступа (или подкласс), даже если этот член объявлен в супертипе.

Из Спецификации языка Java, раздел 6.6.2 :

Пусть C - класс, в котором защищенный член m объявлен. Доступ разрешено только в теле подкласс S C. Кроме того, если Id обозначает поле экземпляра или экземпляр метод, то:

  • Если доступ осуществляется по полному имени Q.Id, где Q - ExpressionName, тогда доступ разрешен, если и только если тип выражения Q является S или подклассом S.
  • Если доступ осуществляется с помощью выражения доступа к полю E.Id, где E является основным выражением или вызовом метода выражение E.Id (...), где E представляет собой Основное выражение, то доступ разрешено, если и только если тип E является S или подклассом S.

Это позволяет типу получать доступ к членам, относящимся к его собственному дереву наследования, без ущерба для инкапсуляции других классов. Например, предположим, что у нас есть:

     A
    / \
   B   Other
  /
 C

и A объявлен защищенным членом x. Без правила, работающего так, как оно работает, вы можете получить инкапсуляцию, поместив элемент в Other:

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

и просто вызывая эту передачу в экземпляре B или C - член фактически станет общедоступным, потому что вы всегда можете обойти это, введя другой класс ... не очень хорошая идея. В соответствии с текущим правилом вам нужно будет создать подкласс B или C, что, в первую очередь, невозможно.

12 голосов
/ 26 октября 2009

Делая это:

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

На самом деле вы не используете тот факт, что вы расширили класс MidiSynth.

Если бы вы попробовали

this.scoreToSec(score);

Тогда вы обнаружите, что имеете доступ к защищенной функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...