11

Javaでは、内部クラスが外部クラスを拡張する場合があります。

たとえば、java.awt.geom.Arc2D.Floatはjava.awt.geom.Arc2Dの内部クラスであり、Arc2Dも拡張します。(http://download.oracle.com/javase/6/docs/api/java/awt/geom/Arc2D.Float.htmlを参照)

また、sun.org.mozilla.javascript.internal.FunctionNode.Jumpは、FunctionNodeのスーパークラスであるsun.org.mozilla.javascript.internal.Nodeを拡張します。(申し訳ありませんが... javadocへのリンクが見つかりません)

私には、これは奇妙に思えます。次に、これらを作成できますか?

new Arc2D.Float.Float() //n.b. I couldn't get this to compile in Intellij IDEA;

new FunctionNode.Jump.Jump.Jump(1); // I could get this to compile

サブクラスをスーパークラスの内部クラスとしてネストすることは、どのような目的に役立ちますか?

スーパークラスの何かにアクセスするのかどうか疑問に思いましたが、親の変数/メソッドにアクセスしたい場合は、

super.variable;

また

super.method();

編集1:jjnguyは、ロジックを同じ場所に保持することを提案しました。その場合、なぜファイルcom.mypackage.AbstractTestを作成しないのでしょうか。

abstract class AbstractTest {
  abstract String getString();
}

class ExtensionTest extends AbstractTest {
  @Override
  String getString() {
    return "hello world";
  }
}

... それよりも:

abstract class AbstractTest {
  abstract String getString();

  class ExtensionTest extends AbstractTest {
    @Override
    String getString() {
      return "hello world";
    }
  }
}

編集2:パッケージの外部でExtensionTestを構築できなかったため、以前の編集での提案に欠陥があることが正しく指摘されています。しかし、私は週末にこれについてさらに考えたので、次はどうですか?

abstract class Test {
  public class ExtensionTest extends AbstractTest {
    @Override
    String getString() {
      return "hello world";
    }
  }

  private abstract class AbstractTest {
    abstract String getString();
  }
} 

本質的に、私がこれまでに見た最良の答えは、内部クラスにその外部クラスを拡張させることで、ロジックをグループ化できるということです。ただし、これは拡張なしで実行できると思います。

私の考えでは、同じサブクラスを無限にネストできるクラスを作成するのは悪い設計のようです。(コンテキスト:これは、コード補完ユーティリティの辞書を作成しようとしたときに発生し、StackOverflowExceptionをスローしました。回避策を見つけましたが、なぜそのように設計されたのか理解できません。)

4

3 に答える 3

15

Javaを見てくださいPoint2D。そのサブクラスである2つの内部クラスがあります。

注意すべき重要なことは、それらがstatic内部クラスであるということです。これは、通常の内部クラスとはまったく異なる意味を持っています。静的メソッドと同様に、静的クラスはオブジェクトレベルではなくクラスレベルで定義されます。

このPoint2D場合、クラスとそのロジックを論理的に結合するために行われます。abstractこのタイプのユーザーは、Point2D使用できる実装を見つけるのに役立ちます。

あなたの編集に応えて、私は1つの重要な事実を指摘したいと思います。単一のJavaファイルには、パブリック内部クラスを除いて、パブリッククラスを1つだけ含めることができます。どちらの例もコンパイルできますが、これらのクラスを一般に公開することはできません。1つのファイルで複数のパブリッククラスを誰かに提示する場合は、パブリック静的内部クラスを使用する必要があります。

于 2011-08-19T17:30:51.410 に答える
9

内部クラスには2つのケースがあります。

  • 静的内部クラス。内部クラスは外部クラスへの参照を保持しません。

  • 非静的内部クラス。内部クラス外部クラスへの参照を保持します。

外部クラスを拡張する静的内部クラスの場合は、外部クラスを拡張する非静的内部クラスほど興味深いものではありません。

後者で何が起こるかというと、内部クラスを作成するには、外部クラスへの参照が必要です。ただし、内部クラスは外部クラスのインスタンスであるため、外部クラスとして使用される内部クラスの別のインスタンスへの参照も受け入れます。

いくつかのコードを見てみましょう:

Outer a = new Outer();
Outer.Inner b = a.new Inner();

// Only possible when Inner extends Outer:
Outer.Inner c = a.new Inner().new Inner();

ビルダーパターンを知っている場合は、これを使用してOOPバージョンを作成できます。

public abstract class Command {

    // Not possible to create the command, else than from this file!
    private Command() {
    }

    public abstract void perform();

    public static class StartComputer extends Command {
        public void perform() {
            System.out.println("Starting Computer");
        }
    }

    public class OpenNotepad extends Command {
        public void perform() {
            Command.this.perform();
            System.out.println("Opening Notepad");
        }
    }

    public class ShutdownComputer extends Command {
        public void perform() {
            Command.this.perform();
            System.out.println("Shutting Computer");
        }
    }

}

これは次のように使用されますnew Command.StartComputer().new OpenNotepad().new ShutdownComputer().perform();

于 2011-08-19T17:45:37.893 に答える
2

最初のものは私のIntelliJでうまくコンパイルされます。

厳密に言えば、静的メンバークラスは内部クラスではありません。それらはネストされたクラスと呼ばれます。

于 2011-08-19T17:45:38.403 に答える