Tak, można tworzyć zarówno zagnieżdżone klasy lub wewnętrzną klasę wewnątrz interfejsu Java (Zauważ, że w przeciwieństwie do popularnego przekonania, że nie ma czegoś takiego jak " statyczne klasy wewnętrzna «: To po prostu nie ma sensu, nie ma nic «wewnętrzny» i nie» outter ”, gdy klasa zagnieżdżona jest statyczna, więc nie może być„ statyczną wewnętrzną ”).
W każdym razie poniższe kompilacje dobrze się komponują:
public interface A {
class B {
}
}
Widziałem, że wstawiał jakiś rodzaj "sprawdzania kontraktu" bezpośrednio w definicji interfejsu (cóż, w klasie zagnieżdżonej w interfejsie, która może mieć statyczne metody, w przeciwieństwie do samego interfejsu, który nie może). Wyglądam tak, jeśli dobrze pamiętam.
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)
}
}
}
Zwróć uwagę, że nie komentuję użyteczności takiej rzeczy, po prostu odpowiadam na twoje pytanie: można to zrobić i jest to jedyny rodzaj wykorzystania, jaki widziałem.
Teraz nie będę komentował przydatności takiego konstruktu i od tego, co widziałem: widziałem go, ale nie jest to zbyt powszechna konstrukcja.
Baza kodów 200KLOC tutaj, gdzie dzieje się to dokładnie zero razy (ale mamy wiele innych rzeczy, które uważamy za złe praktyki, które zdarzają się dokładnie zero razy, a inni ludzie uznaliby to za całkowicie normalne, więc ...).
interface
s nie mogą mieć klas wewnętrznych. Możesz pominąćstatic
modyfikatorinterface
klasy zagnieżdżonej, ale nadal jest to klasa zagnieżdżona, a nie klasa wewnętrzna.B
klasa jest statyczną klasą zagnieżdżoną, a nie klasą wewnętrzną; interfejsy są traktowane w specjalny sposób. Nie mogłem znaleźć wzmianki o tym w Internecie, z wyjątkiem samej specyfikacji: „Klasa składowa interfejsu jest niejawnie statyczna, więc nigdy nie jest uważana za klasę wewnętrzną”. docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3Tak, możemy mieć klasy wewnątrz interfejsów. Jednym z przykładów użycia może być
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(); }
Tutaj kod ma dwie zagnieżdżone klasy, które służą do hermetyzacji informacji o obiektach zdarzeń, które są później używane w definicjach metod, takich jak getKeyEvents (). Umieszczenie ich wewnątrz interfejsu wejściowego poprawia spójność.
źródło
Prawidłowym zastosowaniem, IMHO, jest definiowanie obiektów, które są odbierane lub zwracane przez otaczające metody interfejsu. Typowo struktury przechowujące dane. W ten sposób, jeśli obiekt jest używany tylko dla tego interfejsu, masz rzeczy w bardziej spójny sposób.
Przez przykład:
interface UserChecker { Ticket validateUser(Credentials credentials); class Credentials { // user and password } class Ticket { // some obscure implementation } }
Ale w każdym razie ... to tylko kwestia gustu.
źródło
Cytat ze specyfikacji Java 7 :
NIE jest możliwe deklarowanie niestatycznych klas wewnątrz interfejsu Java, co dla mnie ma sens.
źródło
Ciekawym przypadkiem użycia jest zapewnienie pewnego rodzaju domyślnej implementacji metod interfejsu poprzez klasę wewnętrzną, jak opisano tutaj: https://stackoverflow.com/a/3442218/454667 (aby przezwyciężyć problem dziedziczenia pojedynczej klasy).
źródło
Z pewnością jest to możliwe, a jednym z przypadków, w których uznałem to za przydatne, jest sytuacja, gdy interfejs musi wyrzucać niestandardowe wyjątki. Zachowujesz wyjątki wraz z powiązanym z nimi interfejsem, co, jak sądzę, jest często lepsze niż zaśmiecanie drzewa źródłowego stosami trywialnych plików wyjątków.
interface MyInterface { public static class MyInterfaceException extends Exception { } void doSomething() throws MyInterfaceException; }
źródło
Tak, możliwe jest posiadanie statycznych definicji klas wewnątrz interfejsu, ale być może najbardziej użytecznym aspektem tej funkcji jest użycie typów wyliczeniowych (które są specjalnym rodzajem klas statycznych). Na przykład możesz mieć coś takiego:
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); ... }
źródło
To, o czym wspomina @Bachi, jest podobne do cech w Scali i są w rzeczywistości implementowane za pomocą zagnieżdżonej klasy wewnątrz interfejsu. Można to zasymulować w Javie. Zobacz także cechy java lub wzorzec mieszanki?
źródło
Może jeśli potrzebujesz bardziej złożonych konstrukcji, takich jak różne zachowania implementacyjne, rozważ:
public interface A { public void foo(); public static class B implements A { @Override public void foo() { System.out.println("B foo"); } } }
To jest twój interfejs, a to będzie implementowany:
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(); } }
Może zawierać statyczne implementacje, ale nie będzie to mylące, nie wiem.
źródło
Znalazłem zastosowanie dla tego typu konstrukcji.
Masz dostęp do wszystkich zgrupowanych stałych; nazwa klasy działa w tym przypadku jako przestrzeń nazw.
źródło
Możesz także utworzyć statyczne klasy „Pomocnicze” dla typowych funkcji dla obiektów, które implementują ten interfejs:
public interface A { static class Helper { public static void commonlyUsedMethod( A a ) { ... } } }
źródło
Potrzebuję go teraz. Mam interfejs, w którym wygodnie byłoby zwrócić unikalną klasę z kilku jej metod. Ta klasa ma sens tylko jako kontener dla odpowiedzi z metod tego interfejsu.
Dlatego wygodnie byłoby mieć statyczną definicję klasy zagnieżdżonej, która jest skojarzona tylko z tym interfejsem, ponieważ ten interfejs powinien być jedynym miejscem, w którym ta klasa kontenera wyników jest kiedykolwiek tworzona.
źródło
Na przykład cechy (coś w rodzaju interfejsu z zaimplementowanymi metodami) w Groovy. Są kompilowane do interfejsu, który zawiera wewnętrzną klasę, w której zaimplementowane są wszystkie metody.
źródło