wake-up-neo.com

innere Klasse innerhalb der Schnittstelle

ist es möglich, eine innere Klasse innerhalb eines Interfaces zu erstellen? Wenn ja, warum erstellen wir so? Wie auch immer, werden wir keine Interface-Objekte erstellen?

Helfen sie in einem Entwicklungsprozess?

79
gmhk

Ja, Sie können sowohl eine verschachtelte Klasse als auch eine innere Klasse in einer Java Schnittstelle erstellen (beachten Sie, dass es entgegen der landläufigen Meinung keine "statische innere Klasse) gibt class ": Das macht einfach keinen Sinn, es gibt keine" innere "und keine" äußere "Klasse, wenn eine verschachtelte Klasse statisch ist, sie kann also nicht" statisch inner "sein.

Auf jeden Fall kompiliert die folgende gut:

public interface A {
    class B {
    }
}

Ich habe gesehen, dass es verwendet wurde, um eine Art "Vertragsprüfer" direkt in die Schnittstellendefinition einzufügen (in der Klasse, die in der Schnittstelle verschachtelt ist und statische Methoden haben kann, im Gegensatz zur Schnittstelle selbst, die dies nicht kann). Sieht so aus, wenn ich mich richtig erinnere.

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

Beachten Sie, dass ich die Nützlichkeit einer solchen Sache nicht kommentiere, sondern lediglich Ihre Frage beantworte: Es kann getan werden, und dies ist eine Art von Verwendung, die ich gesehen habe.

Jetzt werde ich nicht auf die Nützlichkeit eines solchen Konstrukts eingehen, und ich habe gesehen: Ich habe es gesehen, aber es ist kein sehr verbreitetes Konstrukt.

200KLOC-Codebasis hier, wo dies genau null Zeit passiert (aber dann haben wir eine Menge anderer Dinge, die wir als schlechte Praktiken betrachten, die auch genau null Zeit passieren, die andere Leute so völlig normal finden würden ...).

41
SyntaxT3rr0r

Ja, wir können Klassen innerhalb von Schnittstellen haben. Ein Beispiel für die Verwendung könnte sein 

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

Hier hat der Code zwei verschachtelte Klassen, die Informationen über Ereignisobjekte einkapseln, die später in Methodendefinitionen wie getKeyEvents () verwendet werden. Wenn sie sich innerhalb der Eingabeschnittstelle befinden, wird die Kohäsion verbessert.

92
zafar142003

Eine gültige Verwendung, IMHO, definiert Objekte, die von den umgebenden Schnittstellenmethoden empfangen oder zurückgegeben werden. Typisch Datenhaltestrukturen. Wenn das Objekt nur für diese Schnittstelle verwendet wird, haben Sie auf diese Weise einen zusammenhängenden Ansatz.

Zum Beispiel:

interface UserChecker {
   Ticket validateUser(Credentials credentials);

   class Credentials {
      // user and password
   }

   class Ticket {
      // some obscure implementation
   }
}

Aber trotzdem ... es ist nur eine Frage des Geschmacks.

40
helios

Zitat aus der Java 7-Spezifikation :

Schnittstellen können Deklarationen für Mitgliedstypen enthalten (§8.5).

Eine Mitgliedstypdeklaration in einer Schnittstelle ist implizit statisch und öffentlich. Es ist zulässig, einen oder beide dieser Modifizierer redundant anzugeben.

Es ist NICHT möglich, nicht statische Klassen innerhalb einer Java-Schnittstelle zu deklarieren, was für mich sinnvoll ist.

28
Nad Nik

Ein interessanter Anwendungsfall ist die Bereitstellung einer Art Standardimplementierung für Schnittstellenmethoden durch eine innere Klasse, wie hier beschrieben: https://stackoverflow.com/a/3442218/454667 (um das Problem der Single-Class- Erbe). 

10
Bachi

Dies ist sicherlich möglich, und ich habe es für nützlich gehalten, wenn eine Schnittstelle benutzerdefinierte Ausnahmen auslösen muss. Sie behalten die Ausnahmen mit der dazugehörigen Schnittstelle, die ich für oft ordentlicher halte, als Ihren Quellbaum mit einer Menge trivialer Ausnahmedateien zu verstreuen.

interface MyInterface {

   public static class MyInterfaceException extends Exception {
   }

   void doSomething() throws MyInterfaceException;
}
7

Ja, es ist möglich, statische Klassendefinitionen in einer Schnittstelle zu haben. Der nützlichste Aspekt dieser Funktion ist jedoch die Verwendung von Aufzählungstypen (spezielle statische Klassen). Zum Beispiel können Sie so etwas haben:

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);
    ...
}
6
raspacorp

Was @Bachi erwähnt, ähnelt den Merkmalen in Scala und wird tatsächlich mithilfe einer verschachtelten Klasse in einer Schnittstelle implementiert. Dies kann in Java simuliert werden. Siehe auch Java-Merkmale oder -Mixins-Muster?

1
Henno Vermeulen

Wenn Sie komplexere Konstruktionen wie verschiedene Implementierungsverhalten wünschen, sollten Sie Folgendes berücksichtigen:

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

Dies ist Ihre Schnittstelle und dies wird der Implementierte sein:

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

Kann einige statische Implementierungen bereitstellen, aber das ist nicht verwirrend. 

1
Ilian Zapryanov

Sie können auch statische "Helper" -Klassen für allgemeine Funktionen für die Objekte erstellen, die diese Schnittstelle implementieren:

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

Ich brauche jetzt einen. Ich habe eine Schnittstelle, wo es zweckmäßig wäre, aus verschiedenen Methoden eine eindeutige Klasse zurückzugeben. Diese Klasse ist nur sinnvollals ein Container für Antworten von Methoden dieser Schnittstelle.

Daher wäre es sinnvoll, eine statische verschachtelte Klassendefinition zu haben, die nur dieser Schnittstelle zugeordnet ist, da diese Schnittstelle die einzige Stelle sein sollte, an der diese Ergebniscontainerklasse erstellt wird.

0
user214420

Zum Beispiel traits (smth like interface mit implementierten Methoden) in Groovy. Sie werden zu einer Schnittstelle kompiliert, die eine innere Klasse enthält, in der alle Methoden implementiert sind. 

0
dehasi

Ich habe eine Verwendung für diese Art von Konstrukt gefunden.

  1. Mit diesem Konstrukt können Sie alle statischen Endkonstanten definieren und gruppieren.
  2. Da es sich um eine Schnittstelle handelt, können Sie diese in einer Klasse implementieren. 

Sie haben Zugriff auf alle gruppierten Konstanten. Der Name der Klasse fungiert in diesem Fall als Namespace.

0
Venkat K