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


97

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

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

回答:


51

はい、Javaインターフェース内にネストされたクラスと内部クラスの両方作成できます(一般的に、「静的内部クラス」などは存在しないと信じています。これは単に意味がなく、「内部」も「も」はありません。入れ子になったクラスが静的である場合、「外部」クラスであるため、「静的内部」にすることはできません。

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

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)
        }
    }
}

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

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

これが正確にゼロタイムで発生するここ200KLOCコードベース(ただし、他の人が完全に正常であると感じるほど正確にゼロタイムで発生する悪い慣行を考慮する他の多くの事柄があります...)。


使用例をいくつか追加できますか?私は少し前に似たようなものをテストしましたが、この構造を使用して何を得ることができるのか理解していません。
ローマ

@Roman:あるプロジェクトでこれに遭遇したのを覚えています(比較的クリーンなプロジェクトを追加しますが、私のプロジェクトではありませんでした)が、本当にクリーンかどうかはわかりません。私が見たような小さな例を追加しましたが、もう一度言います。これは私のコードではなく、その構造を使用していないため、有効な例を思い付くのに最も適格ではありません:) IIRC内部のクラスは常にStateCheckerなどの名前が付けられ、呼び出しは常に次のようになります。A.StateChecker.check(a)またはそのようなもの。
SyntaxT3rr0r 2010年

8
「「静的内部クラス」などは存在しない」と言った場合、「Javaインターフェース内にネストされたクラスと内部クラスの両方作成できる」という答えは根本的に間違っています。絞り込まれた定義を使用すると、は内部クラスを持つinterfaceことができません。のネストされたクラスのstatic修飾子は省略できますがinterface、それでもネストされたクラスであり、内部クラスではありません。
Holger

6
この答えは間違っています。インターフェイスは静的な入れ子クラスを持つことができますが、内部クラスを持つことはできません。
Paul Boddington、2015年

1
@PaulBoddingtonそうですね。「静的」を削除しても、Bクラスは静的なネストされたクラスであり、内部クラスではありません。インターフェイスは特別な扱いを受けます。仕様自体を除いて、オンラインでの言及は見つかりませんでした。「インターフェイスのメンバークラスは暗黙的に静的であるため、内部クラスとは見なされません。」docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Max Barraclough

109

はい、インターフェイス内にクラスを含めることができます。使用法の一例は

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();
}

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


3
@Levit疑問に思って、実装されたクラスはどのように見えるでしょうか?
オーバーエクスチェンジ

1
上記の使用法の実装が動作するのを見てみたいと思います。ありがとうございました。
Prakash K

45

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

例として:

interface UserChecker {
   Ticket validateUser(Credentials credentials);

   class Credentials {
      // user and password
   }

   class Ticket {
      // some obscure implementation
   }
}

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


34

Java 7仕様からの引用:

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

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

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


ありがとうございました。これはおそらく、すべての中で最も簡潔な答えです。
ジョセフ

1
これは私が探していた答えですが、OPはいくつかの質問をします。
チャーリーウォレス

11

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


そして、これがまさにプライベートメンバークラスが理にかなっている理由です。
ヴィンセント

7

それは確かに可能であり、私がそれが有用であるとわかった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);
    ...
}


1

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

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();
    }
}

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


0

私はこのタイプの構造の使用を見つけました。

  1. この構成を使用して、すべての静的最終定数を定義およびグループ化できます。
  2. それは、これをクラスに実装できるインターフェースであるためです。

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


0

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

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

0

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

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


0

たとえば、Groovyの特性(実装されたメソッドとのインターフェースのようなもの)です。それらは、すべてのメソッドが実装される内部クラスを含むインターフェースにコンパイルされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.