Klasa wewnętrzna w interfejsie

Czy możliwe jest utworzenie wewnętrznej klasy w interfejsie? Jeśli tak, to dlaczego tworzymy w ten sposób? W każdym razie nie będziemy tworzyć żadnych obiektów interfejsu?

Czy pomagają w jakimkolwiek procesie rozwoju?

Author: skaffman, 2010-03-08

13 answers

Tak, ty możesz utworzyć zarówno klasę zagnieżdżoną, jak i klasę wewnętrzną wewnątrz interfejsu Java (zauważ, że w przeciwieństwie do popularnego przekonania, nie ma czegoś takiego jak "static inner class": to po prostu nie ma sensu, nie ma nic "inner" ani "outter", gdy Klasa zagnieżdżona jest statyczna, więc nie może być "static inner").

W każdym razie, następujące kompiluje dobrze:

public interface A {
    class B {
    }
}

Widziałem, jak umieszczał jakiś "kontroler kontraktów" 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ąda 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)
        }
    }
}

Zauważ, że nie komentuję przydatności takiego czegoś, po prostu odpowiadam na twoje pytanie: da się to zrobić i to jest jeden rodzaj zastosowania, jaki z tego widziałem.

Teraz Nie będę komentował przydatności takiej konstrukcji i z tego co widziałem: widziałem, ale nie jest to zbyt częste konstruuj.

200kloc codebase tutaj, gdzie dzieje się to dokładnie zero czasu (ale wtedy mamy wiele innych rzeczy, które uważamy za złe praktyki, które zdarzają się dokładnie zero czasu zbyt, że inni ludzie uważają zupełnie normalne tak...).

 38
Author: SyntaxT3rr0r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 11:30:23

Tak, 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(). Posiadanie ich wewnątrz interfejsu wejściowego poprawia spójność.

 84
Author: zafar142003,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-11 03:49:57

Poprawnym zastosowaniem, IMHO, jest definiowanie obiektów, które są odbierane lub zwracane przez metody interfejsu. Tipically Data holding structures. 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 tak czy inaczej... to tylko kwestia gustu.
 37
Author: helios,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 11:47:49

Cytat z Java 7 spec:

Interfejsy mogą zawierać deklaracje typu member (§8.5).

Deklaracja typu member w interfejsie jest domyślnie statyczna i publiczna. Dozwolone jest redundantne określanie jednego lub obu tych modyfikatorów.

Nie jest możliwe deklarowanie niestatycznych klas wewnątrz interfejsu Java, co ma dla mnie sens.

 25
Author: Nad Nik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-22 00:02:59

Interesującym przypadkiem użycia jest dostarczenie pewnego rodzaju domyślnej implementacji do metod interfejsu poprzez wewnętrzną klasę, jak opisano tutaj: https://stackoverflow.com/a/3442218/454667 (aby przezwyciężyć problem dziedziczenia jednoklasowego).

 10
Author: Bachi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:33

Z pewnością jest to możliwe, a jednym z przypadków, w którym uznałem to za przydatne, jest sytuacja, w której interfejs musi rzucać niestandardowe wyjątki. Zachowaj wyjątki z powiązanym interfejsem, który moim zdaniem jest często bardziej schludny niż zaśmiecanie drzewa źródłowego stertami trywialnych plików WYJĄTKÓW.

interface MyInterface {

   public static class MyInterfaceException extends Exception {
   }

   void doSomething() throws MyInterfaceException;
}
 7
Author: Michael Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-14 03:59:39

Tak, możliwe jest posiadanie statycznych definicji klas wewnątrz interfejsu, ale być może najbardziej przydatnym aspektem tej funkcji jest użycie typów enum (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);
    ...
}
 6
Author: raspacorp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 02:18:44

To, o czym wspomina @Bachi, jest podobne do cech w Scali i jest zaimplementowane przy użyciu zagnieżdżonej klasy wewnątrz interfejsu. Można to symulować w Javie. Zobacz też cechy Javy czy wzór mixins?

 1
Author: Henno Vermeulen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:33

Może, jeśli chcesz 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 i to będzie implementacja:

    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 dostarczyć jakieś statyczne implementacje, ale nie będzie to mylące, Nie wiem.

 1
Author: Ilian Zapryanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 19:43:38

Znalazłem zastosowanie fir tego typu konstrukcji.

  1. możesz użyć tego konstruktu do zdefiniowania i pogrupowania wszystkich statycznych stałych końcowych.
  2. ponieważ jest to interfejs, który możesz zaimplementować na klasie.

Masz dostęp do wszystkich stałych pogrupowanych; nazwa klasy działa w tym przypadku jako przestrzeń nazw.

 0
Author: Venkat K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-02 18:07:40

Można również tworzyć statyczne klasy "Helper" dla wspólnej funkcjonalności dla obiektów implementujących ten interfejs:

public interface A {
    static class Helper {
        public static void commonlyUsedMethod( A a ) {
           ...
        }
    }
}
 0
Author: Victor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 19:21:21

Potrzebuję go teraz. Mam interfejs, w którym wygodnie byłoby zwrócić unikalną klasę z kilku jego metod. Ta klasa ma tylko sens jako kontener odpowiedzi z metod tego interfejsu.

Stąd byłoby wygodne posiadanie statycznej, zagnieżdżonej definicji klasy, która jest powiązana tylko z tym interfejsem, ponieważ ten interfejs powinien być jedynym miejscem, w którym ta klasa kontenera results jest kiedykolwiek tworzona.

 0
Author: user214420,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-13 22:03:02

Na przykład traits (smth jak interfejs z zaimplementowanymi metodami) w Groovy. Są one kompilowane do interfejsu, który zawiera wewnętrzną klasę, w której zaimplementowane są wszystkie metody.

 0
Author: dehasi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-13 22:10:06