web-dev-qa-db-ja.com

インターフェイス内の内部クラス

インターフェイス内に内部クラスを作成することは可能ですか?可能であれば、インターフェイスオブジェクトを作成しないので、なぜそのような内部クラスを作成するのでしょうか。

これらの内部クラスは開発プロセスに役立ちますか?

86
gmhk

はい、can Javaインターフェイス内にネストされたクラスまたは内部クラスの両方を作成します(一般的な信念に反して、 "static inner class ":これはまったく意味がありません。ネストされたクラスが静的である場合、「内部」および「外部」クラスはないため、「静的内部」にはなりません)。

とにかく、次のコードは問題なくコンパイルされます。

public interface A {
    class B {
    }
}

私は、インターフェイス定義に何らかの「コントラクトチェッカー」を直接配置するのを見てきました(インターフェイスにネストされたクラスでは、インターフェイス自体に反して静的メソッドを持つことができますが、できません)。正しく思い出せばこのように見える。

public interface A {
    static class B {
        public static boolean verifyState( A a ) {
            return (true if object implementing class A looks to be in a valid state)
        }
    }
}

私はそのようなことの有用性についてコメントしていないことに注意してください、私はあなたの質問に単に答えているだけです。

今、私はそのようなコンストラクトの有用性についてコメントせず、私は見ました:私はそれを見ましたが、それは非常に一般的なコンストラクトではありません。

ここで200KLOCコードベースは、これが正確にゼロ時間で発生します(しかし、他の人が完全に正常であると思うので、正確にゼロ時間で発生する悪い習慣を考慮する他の多くのことを持っています...)。

41
SyntaxT3rr0r

はい、インターフェイス内にクラスを作成できます。使用法の一例は

public interface Input
{
    public static class KeyEvent {
         public static final int KEY_DOWN = 0;
         public static final int KEY_UP = 1;
         public int type;
         public int keyCode;
         public char keyChar;
    }
    public static class TouchEvent {
         public static final int TOUCH_DOWN = 0;
         public static final int TOUCH_UP = 1;
         public static final int TOUCH_DRAGGED = 2;
         public int type;
         public int x, y;
         public int pointer;
    }
    public boolean isKeyPressed(int keyCode);
    public boolean isTouchDown(int pointer);
    public int getTouchX(int pointer);
    public int getTouchY(int pointer);
    public float getAccelX();
    public float getAccelY();
    public float getAccelZ();
    public List<KeyEvent> getKeyEvents();
    public List<TouchEvent> getTouchEvents();
}

ここで、コードには、後でgetKeyEvents()などのメソッド定義で使用されるイベントオブジェクトに関する情報をカプセル化するための2つのネストされたクラスがあります。 Inputインターフェイス内に配置すると、凝集度が向上します。

100
zafar142003

有効な使用法であるIMHOは、囲んでいるインターフェイスメソッドによって受信または返されるオブジェクトを定義しています。一般的にデータ保持構造。そのようにして、オブジェクトがそのインターフェースにのみ使用される場合、よりまとまりのあるものになります。

例:

interface UserChecker {
   Ticket validateUser(Credentials credentials);

   class Credentials {
      // user and password
   }

   class Ticket {
      // some obscure implementation
   }
}

とにかく...それは好みの問題です。

40
helios

Java 7仕様 からの引用:

インターフェイスには、メンバー型宣言(§8.5)を含めることができます。

インターフェイスのメンバー型宣言は、暗黙的に静的でパブリックです。これらの修飾子のいずれかまたは両方を冗長に指定することは許可されています。

Javaインターフェース内で非静的クラスを宣言することはできません。これは理にかなっています。

30
Nad Nik

興味深いユースケースは、ここで説明するように、内部クラスを介してメソッドをインターフェースするデフォルトの実装を提供することです: https://stackoverflow.com/a/3442218/454667 (単一の問題を克服するため-クラス継承)。

10
Bachi

確かにそれは可能です、そして、私がそれが役に立つとわかった1つのケースは、インターフェースがカスタム例外を投げなければならないときです。関連付けられたインターフェイスを使用して例外を保持します。これは、多くの場合、些細な例外ファイルでソースツリーを散らかすよりもきれいだと思います。

interface MyInterface {

   public static class MyInterfaceException extends Exception {
   }

   void doSomething() throws MyInterfaceException;
}
7

はい、インターフェイス内に静的クラス定義を含めることは可能ですが、おそらくこの機能の最も有用な側面は、列挙型(静的クラスの特別な種類)を使用する場合です。たとえば、次のようなものを使用できます。

public interface User {
    public enum Role {
        ADMIN("administrator"),
        EDITOR("editor"),
        Vanilla("regular user");

        private String description;

        private Role(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    public String getName();
    public void setName(String name);
    public Role getRole();
    public void setRole(Role role);
    ...
}
7
raspacorp

@Bachiが言及していることは、Scalaの特性に似ており、実際にはインターフェース内のネストされたクラスを使用して実装されます。これはJavaでシミュレートできます。参照

1
Henno Vermeulen

いくつかの異なる実装動作のようなより複雑な構成が必要な場合は、次のことを考慮してください。

    public interface A {
    public void foo();
    public static class B implements A{
        @Override
        public void foo(){
            System.out.println("B foo");
        }
    }
}

これがあなたのインターフェースであり、これが実装先になります:

    public class C implements A {
    @Override
    public void foo(){ A.B b = new A.B(); b.foo(); }


    public static void main(String[] strings) {
        C c = new C();
        c.foo();
    }
}

いくつかの静的な実装を提供するかもしれませんが、それは混乱しないでしょう、私にはわかりません。

1
Ilian Zapryanov

このインターフェイスを実装するオブジェクトの一般的な機能のために、「ヘルパー」静的クラスを作成することもできます。

public interface A {
    static class Helper {
        public static void commonlyUsedMethod( A a ) {
           ...
        }
    }
}
0
Victor

今すぐ必要です。いくつかのメソッドから一意のクラスを返すのに便利なインターフェイスがあります。このクラスは、このインターフェイスのメソッドからの応答のコンテナとしてのみ意味があります。

したがって、このインターフェイスはこの結果コンテナクラスが作成される唯一の場所である必要があるため、このインターフェイスのみに関連付けられている静的なネストされたクラス定義を持つと便利です。

0
Mr.What

例えば、Groovyの traits (実装されたメソッドを持つインターフェースのようなsms)。これらは、すべてのメソッドが実装されている内部クラスを含むインターフェイスにコンパイルされます。

0
dehasi

私はこのタイプのコンストラクトの使用を見つけました。

  1. このコンストラクトを使用して、すべての静的最終定数を定義およびグループ化できます。
  2. なぜなら、これはクラスでこれを実装できるインターフェースです。

グループ化されたすべての定数にアクセスできます。この場合、クラスの名前は名前空間として機能します。

0
Venkat K