2009-10-25 9 views
7

は、保護されたメソッドのドキュメントです:なぜ私は保護されたJavaメソッドにアクセスできないのですか?ここ

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

Najib Tounsi(コメントが不十分な担当者)から:「synth.scoreToSeq(score);」は正当なものでなければなりません。 –

答えて

16

(EDIT:theycallmemorty's answer回避する実践的なアドバイスを提供しますこの回答は、そのアドバイスに従わなければならない理由、すなわちなぜその言語がそのように設計されたのかという理由を説明しています。

プロテウスたとえメンバーがであるにもかかわらず、アクセスコード(またはサブクラス)と同じタイプの別のオブジェクトのメンバーである場合は、スーパータイプでと宣言されます。 Java Language Specification, section 6.6.2から

Cは 保護部材mが宣言されているクラスとします。同上 は、インスタンスフィールドまたはインスタンス 方法表す場合アクセス は、唯一またC.の サブクラスSの本体内に許可されている:アクセスが修飾名であると

  • をQ.Id QがExpressionNameの場合 式 の型がSまたはSのサブクラスである場合にのみ、 の場合はアクセスが許可されます。
  • アクセスがフィールドアクセス式E.Idである場合、 Eはプライマリ 式であるか、メソッド呼び出しである 式E.Id(。。)、wここでEは、アクセスが 場合は許可され、E のタイプがこのタイプはに関連するメンバーにアクセスできるようにするためにSまたはS.
  • のサブクラス

ですされている場合にのみ、 一次式でありますそれ自身の継承ツリー、他のクラスのカプセル化を破ることなく例えば、我々が持っているとします

 A 
    /\ 
    B Other 
/
C 

とAは、保護されたメンバーxを宣言しました。それがない方法を作業ルールがなければ、あなたはOtherにメンバーを置くことによってラウンドカプセルを得ることができます:

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

だけBまたはCのインスタンスを渡すことを呼び出す - メンバーが効果的に公共になる、あなたのために別のクラスを導入することでいつもそれを回避することができます...良い考えではありません。現在のルールでは、BまたはCのサブクラスを作成する必要があります。これは最初にできない場合があります。これにより

+1

私は(ほとんど)JLSの抜粋を理解していると思いますが、反例は説得力がないようです。保護されたフィールドxは、BまたはCにはないAの上にあるので、他の人がそれを見ることはOKであるはずです。 BまたはCの他のフィールドは公開されていません。 もちろん、これは主にヘアスプリットです。その答えは「スペックはそうです」で、スペックを変更することはおそらく不可能です:-) –

+0

@Jon何をする2番目の最後の行に「別のクラスを導入することで常に回避できるから」という意味ですか? – Geek

+1

@Geek:誰でも 'A'を拡張し、' A'の他の*サブクラスのインスタンスへのアクセスを提供する別のクラスを作成することができます。 –

12

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

は、あなたが実際にあなたがMidiSynthクラスを拡張しましたという事実を利用していません。

あなたは

this.scoreToSec(score); 

をしようとしていたなら、あなたはあなたが保護された機能へのアクセス権を持っています。

+4

また、MidiSynthの代わりに新しいMidiSequenceを作成して(シンセ変数のタイプも変更して) –

関連する問題