インターフェイス内に内部クラスを作成することは可能ですか?
可能であれば、インターフェイスオブジェクトを作成しないので、なぜそのような内部クラスを作成したいのでしょうか。
これらの内部クラスは、開発プロセスに役立ちますか?
インターフェイス内に内部クラスを作成することは可能ですか?
可能であれば、インターフェイスオブジェクトを作成しないので、なぜそのような内部クラスを作成したいのでしょうか。
これらの内部クラスは、開発プロセスに役立ちますか?
はい、インターフェイス内にクラスを含めることができます。使用法の一例は次のとおりです。
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()などのメソッド定義で使用されるイベントオブジェクトに関する情報をカプセル化するためのものです。それらを入力インターフェイス内に配置すると、凝集性が向上します。
はい、 Javaインターフェース内にネストされたクラスまたは内部クラスの両方を作成できます(一般的な信念に反して、「静的内部クラス」のようなものはありません。これは単に意味がなく、「内部」も「内部」もありません。ネストされたクラスが静的である場合は「outter」クラスであるため、「staticinner」にすることはできません。
とにかく、以下はうまくコンパイルされます:
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コードベースは、これが正確にゼロ時間で発生します(ただし、他の人が完全に正常であると感じるような、正確にゼロ時間で発生する悪いプラクティスを考慮する他の多くのものがあります...)。
有効な使用法であるIMHOは、囲んでいるインターフェイスメソッドによって受信または返されるオブジェクトを定義することです。通常、データ保持構造。このように、オブジェクトがそのインターフェースにのみ使用される場合は、よりまとまりのある方法で物事を行うことができます。
例:
interface UserChecker {
Ticket validateUser(Credentials credentials);
class Credentials {
// user and password
}
class Ticket {
// some obscure implementation
}
}
しかしとにかく...それは好みの問題です。
Java 7仕様からの引用:
インターフェイスには、メンバータイプ宣言(§8.5)を含めることができます。
インターフェイスのメンバー型宣言は、暗黙的に静的でパブリックです。これらの修飾子のいずれかまたは両方を冗長に指定することが許可されています。
Javaインターフェース内で非静的クラスを宣言することはできません。これは私には理にかなっています。
興味深いユースケースは、https://stackoverflow.com/a/3442218/454667(単一クラスの継承の問題を克服するため)で説明されているように、内部クラスを介してメソッドをインターフェースするための一種のデフォルト実装を提供することです。
それは確かに可能であり、私がそれが有用だと思った1つのケースは、インターフェースがカスタム例外をスローしなければならない場合です。例外を関連付けられたインターフェイスで保持します。これは、ソースツリーに些細な例外ファイルのヒープを散らかすよりも優れていることが多いと思います。
interface MyInterface {
public static class MyInterfaceException extends Exception {
}
void doSomething() throws MyInterfaceException;
}
はい、インターフェイス内に静的クラス定義を含めることは可能ですが、この機能の最も有用な側面は、列挙型(特殊な種類の静的クラス)を使用する場合です。たとえば、次のようなものを使用できます。
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);
...
}
@Bachiが言及していることは、Scalaの特性に似ており、実際にはインターフェース内のネストされたクラスを使用して実装されます。これはJavaでシミュレートできます。Javaの特性またはミックスインパターンも参照してください。
いくつかの異なる実装動作のようなより複雑な構造が必要な場合は、次のことを検討してください。
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();
}
}
いくつかの静的な実装を提供するかもしれませんが、それは混乱しないでしょう、私は知りません。
私はこのタイプの構成の使用を見つけました。
グループ化されたすべての定数にアクセスできます。この場合、クラスの名前は名前空間として機能します。
このインターフェイスを実装するオブジェクトの一般的な機能のために、「ヘルパー」静的クラスを作成することもできます。
public interface A {
static class Helper {
public static void commonlyUsedMethod( A a ) {
...
}
}
}
今必要です。いくつかのメソッドから一意のクラスを返すのに便利なインターフェイスがあります。このクラスは、このインターフェイスのメソッドからの応答のコンテナとしてのみ意味があります。
したがって、このインターフェイスは、この結果コンテナクラスが作成される唯一の場所である必要があるため、このインターフェイスにのみ関連付けられている静的なネストされたクラス定義があると便利です。
たとえば、Groovyの特性(実装されたメソッドとのインターフェースのようなsmth)。これらは、すべてのメソッドが実装されている内部クラスを含むインターフェイスにコンパイルされます。