2012-03-01 7 views
66

プライベートメソッドをfinalとして宣言するのが理にかなっているのだろうと思っていました。しかし、私は独占的な状況があると想像し、それを理解するコードを書いた:なぜ内部クラスはプライベートな最終メソッドをオーバーライドできますか?

public class Boom { 

    private void touchMe() { 
     System.out.println("super::I am not overridable!"); 
    } 

    private class Inner extends Boom { 

     private void touchMe() { 
      super.touchMe(); 
      System.out.println("sub::You suck! I overrided you!"); 
     } 
    } 

    public static void main(String... args) { 
     Boom boom = new Boom(); 
     Boom.Inner inner = boom.new Inner(); 
     inner.touchMe(); 
    } 
} 

それはコンパイルされ、働いた。 "私は)(touchMeを行い、最終的なはずです" 私は考えて、それをやった:

public class Boom { 

    private final void touchMe() { 
     System.out.println("super::I am not overridable!"); 
    } 

    private class Inner extends Boom { 

     private void touchMe() { 
      super.touchMe(); 
      System.out.println("sub::You suck! I overrided you!"); 
     } 
    } 

    public static void main(String... args) { 
     Boom boom = new Boom(); 
     Boom.Inner inner = boom.new Inner(); 
     inner.touchMe(); 
    } 
} 

、それはまた、動作してくれ

[email protected]:~$ java Boom 
super::I am not overridable! 
sub::You suck! I overrided you! 

理由を告げますか?

+0

「隠れている」または「シャドウイン」などです。なぜ外部クラスを拡張するのがちょっと悪いのか(つまりenumであっても)/Try 'Boom inner = boom.new Inner();' –

+23

@Overrideアノテーションを使用する理由の良い例です。実際にメソッドをオーバーライドしていることを確認してください – Shawn

+0

'super ...'を2回書いてはいけませんか? *更新*いいえ。そうですか。 – DerMike

答えて

87

プライベートメソッドをオーバーライドすることはできません(プライベートメソッドは継承されません)。実際にプライベートメソッドをfinal宣言しても違いはありません。

Boom.touchMeBoom.Inner.touchMeの2つのメソッドは、2つの完全に別々のメソッドで、同じ識別子を共有しています。 super.touchMetouchMeとは異なるメソッドを参照しているという事実は、Boom.Inner.touchMeシャドウBoom.touchMe(上書きされていないため)であるからです。

これは、いくつかの方法で証明することができる。

  • あなた自身を発見したとして、あなたが公共のようにメソッドを変更する場合は、が突然最終的に上書きしようとしているため、コンパイラは文句を言うだろう方法。

  • メソッドをプライベートにしておき、@Overrideアノテーションを追加すると、コンパイラは不平を言います。

  • alpianが指摘するように、あなたがBoomオブジェクト(((Boom) inner).touchMe())にBoom.Innerオブジェクトをキャストした場合、Boom.touchMeが(それが実際に上書きされた場合、キャストは重要ではないだろう)と呼ばれています。

関連質問:

+13

私はこの上で間違っているかもしれないが、私は、キーの誤解が 'super.touchMeは()'「このメソッドのオーバーライドメソッドを呼び出します。」を意味していることであると信じてそれはしばしばそのように機能しますが、実際には「このクラスが継承するクラスでtouchMe()メソッドを呼び出す」という意味です。だから、あなたは 'super.touchMe()'を呼び出すことができます - それはたまたま(同じ署名を持つ)メソッドも持っています。 – corsiKa

+1

はい、ありがとうございます!分かりました。私はそれを公開したとき、私はコンパイル時のエラーを得ました。 – chicout

+0

ようこそ。 :-) – aioobe

2

それは各クラスにprivateであるため、あなたがメソッドをオーバーライドすることができます。

6

プライベートメソッドは、サブクラスまたは実際に他のクラスからは見えないため、同じ名前を持つことができますが、互いにオーバーライディングしているわけではありません。

@Overrideアノテーションを追加してみてください。コンパイラエラーが発生します。

+1

"私的な方法は...他のどのクラスにも見えません" - あなたが反射を考慮するまで –

+0

True - しかし、それは元の質問の範囲外で、乗り越えの問題には影響しないと思います。 – DNA

8

私は次のように実際には2つの別々の方法がここに存在するという事実がうまくあなたのメインを変更することによって実証されたと思う:

public static void main(String... args) { 
    Boom boom = new Boom(); 
    Boom.Inner inner = boom.new Inner(); 
    inner.touchMe(); 
    System.out.println("And now cast it..."); 
    ((Boom)(inner)).touchMe(); 
} 

この今印刷します

super::I am not overridable! 
sub::You suck! I overrided you! 
And now cast it... 
super::I am not overridable! 

と理由コールいますInnersuper作品にあなたはそれが同じCであるとして実際に存在し、Innerに表示されている、あなたのスーパークラス(Boom)でtouchMeと呼ばれる方法を探しているされているため、ラス。

1

あなただけの同じ名前の別のメソッドを宣言しました。内部クラスはそれ自身がクラスのメンバーであるため、クラスのプライベートメンバーを呼び出すことができます。この変更により詳細に説明されることを願っています。

public class Boom { 

    private final void touchMe() { 
     System.out.println("super [touchMe] ::I am not overridable!"); 
    } 

    public void overrideMe(){ 
     System.out.println("super [overrideMe]::I am overridable!"); 
    } 

    private class Inner extends Boom { 

     private void touchMe() { 
      super.touchMe(); 
      System.out.println("sub [touchMe]::You suck! I overrided you!"); 
     } 

     public void overrideMe(){ 
      System.out.println("sub [overrideMe] ::I overrided you!"); 
     } 
    } 

    public static void main(String... args) { 
     Boom boom = new Boom(); 
     Boom.Inner inner = boom.new Inner(); 

     inner.touchMe(); 

     Boom newBoom = inner; 
     newBoom.touchMe(); 
     newBoom.overrideMe(); 
    } 
} 



super [touchMe] ::I am not overridable! 
sub [touchMe]::You suck! I overrided you! 
super [touchMe] ::I am not overridable! 
sub [overrideMe] ::I overrided you! 
関連する問題