2009-10-25 13 views
7

Hier ist die Dokumentation für die geschützte Methode:Warum kann ich nicht auf die geschützte Java-Methode zugreifen, obwohl ich die Klasse erweitert habe?

/** Converts jmusic score data into a MIDI Sequence */ 
protected javax.sound.midi.Sequence scoreToSeq(Score score) 

Und ich habe diese kleine Klasse die Klasse, die scoreToSeq Methode kommt zu verlängern:

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

Von Najib Tounsi (nicht genug rep zu kommentieren): Obwohl, 'synth.scoreToSeq (score);' sollte legal sein. –

Antwort

16

(EDIT: theycallmemorty's answer gibt die praktischen Ratschläge zur Vermeidung von In dieser Antwort finden Sie die Gründe, warum Sie diesen Rat befolgen müssen, dh warum die Sprache so entworfen wurde.

Sie können nur auf einen Schutz zugreifen Mitglied eines anderen Objekts, das vom gleichen Typ wie der zugreifende Code (oder eine Unterklasse) ist - obwohl das Mitglied in einem Supertyp deklariert ist.

Vom Java Language Specification, section 6.6.2:

Sei C die Klasse, in der ein geschützt Mitglied m deklariert wird. Zugang ist nur innerhalb des Körpers eines Subklasse S von C. Zusätzlich gestattet, wenn Id ein Instanz-Instanz-Feld oder Verfahren bezeichnet, dann gilt:

  • Wenn der Zugriff durch einen qualifizierten Namen ist Q.Id , wobei Q ein ExpressionName ist, dann der Zugriff erlaubt ist, wenn und nur wenn der Typ des Ausdrucks Q S oder eine Unterklasse von S.
  • wenn der Zugriff durch einen Feldzugriff Ausdruck ist E.Id, wobei E ist ein primärer Ausdruck oder durch einen Methodenaufruf Ausdruck E.Id (...), W hier E ist ein Primärer Ausdruck, dann wird der Zugriff zulässig, wenn und nur wenn die Art der E S oder eine Unterklasse von S.

Dies ist eine Art zu ermöglichen, ist Mitglieder relevant sind für den Zugriff auf einen eigenen Vererbungsbaum, ohne die Kapselung anderer Klassen zu vereiteln. Angenommen, wir haben:

 A 
    /\ 
    B Other 
/
C 

und A erklärte ein geschütztes Mitglied x. Ohne die Regel die Art und Weise funktioniert es der Fall ist, könnten Sie rund Verkapselung erhalten, indem ein Mitglied in Other setzen:

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

und nur fordern, dass in einer Instanz von B oder C vorbei - das Mitglied wirksam öffentlich werden würde, weil Sie Ich konnte immer damit umgehen, indem ich eine andere Klasse einführte ... keine gute Idee. Mit der aktuellen Regel müssten Sie die Unterklasse B oder C - die Sie möglicherweise nicht an erster Stelle sein können.

+1

Ich glaube, ich verstehe (meistens) den JLS-Auszug :-), aber das Gegenbeispiel scheint nicht überzeugend zu sein. Das geschützte Feld x steht auf A, nicht auf B oder C, also sollte es für andere OK sein, es zu sehen. Es stellt keine anderen Felder von B oder C zur Verfügung. Natürlich ist dies meistens haarsträubend, da die Antwort "die Spezifikation sagt es so" und es ist ziemlich unwahrscheinlich, dass wir die Spezifikation ändern :-) –

+0

@Jon Was tun Sie meinen mit "weil Sie immer daran arbeiten könnten, indem Sie eine andere Klasse einführen" in Ihrer vorletzten Zeile? – Geek

+1

@Geek: Jeder könnte einfach eine andere Klasse erstellen, die 'A' erweitert und Zugriff auf eine Instanz von * jeder anderen * Unterklasse von' A' bietet. –

12

Auf diese Weise:

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

Sie sind eigentlich nicht die Vorteile der Tatsache, dass Sie die MidiSynth Klasse erweitert haben.

Wenn Sie

this.scoreToSec(score); 

versuchen, waren dann werden Sie feststellen, haben Sie Zugriff auf die geschützte Funktion.

+4

Oder indem Sie eine neue MidiSequence anstelle von MidiSynth erstellen (und auch den Typ der Synth-Variablen ändern). –

Verwandte Themen