почему я не могу получить доступ к защищенному java-методу, даже если думал, что расширил класс?

StackOverflow https://stackoverflow.com/questions/1622219

  •  06-07-2019
  •  | 
  •  

Вопрос

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

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

    }
}
Это было полезно?

Решение

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

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

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

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

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

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

     A
    / \
   B   Other
  /
 C

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

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

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

Другие советы

Делая это:

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

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

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

this.scoreToSec(score);

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top