2012-04-15 5 views
5

Więc mam tego interfejsuTyp Erasure wychowuje swoją brzydką głowę, jak ominąć?

public interface EventHandler<E extends EventObject> 
{ 
    public void handleEvent(E event); 
} 

i chcę czerpać to, że zajęcia dla obsługi zdarzeń, tak jak poniżej:

public class WorkingHandler implements EventHandler<MouseEvent> 
{ 
    public void handleEvent(MouseEvent event) 
    { 
     //handle event 
    } 
} 

Powyższy przykład działa dobrze. Ale kompilator nie pozwoli mi zaimplementować EventHandler wiele razy, ze względu na bardzo frustrujące Errors Typu .

public class NotWorkingHandler implements EventHandler<MouseEvent>, EventHandler<KeyEvent> 
{ 
    public void handleEvent(MouseEvent event) 
    { 
     //handle mouse event 
    } 

    public void handleEvent(KeyEvent event) 
    { 
     //handle key event 
    } 
} 

Kilka pytań ...

  1. Dlaczego Java nie pozwalają Type Erasure? IIRC ma coś wspólnego z kompatybilnością z wcześniejszymi wersjami Javy, prawda?

EDIT: To znaczy dlaczego Java mieć Type Erasure (miał to na odwrót)

  1. Czy istnieje jakiś rodzaj „mod”/„rozszerzeniem” (z braku lepszego słowa) lub języków programowania, które pozwalają mi ominąć typ Erasure? Ponieważ nie używam starszych wersji Javy, nie obchodzi mnie, że mój kod jest zgodny ze starszym kodem.

  2. Czy są jakieś obejścia w języku Java, których mogę użyć, aby ominąć typ Erasure?

  3. Jeśli nie, jakie są alternatywne sposoby kodowania obsługi zdarzeń w moim programie, który zapewnia kompilatorowi szczęście?

+4

-- nie ma sensu. Java pozwala na wymazywanie typów - w rzeczywistości implementuje wymazywanie typów. – emory

+0

"Czy jest jakiś rodzaj" mod "/" rozszerzenie "(z braku lepszego słowa) lub języków programowania, które pozwalają mi ominąć typ Erasure?" - Tak, wiele języków nie ma wymazania typów. – emory

+1

Szukasz C# –

Odpowiedz

1

nie jestem pewien, że zrozumienie Rodzaj Erasure w Javie jest poprawna. Jak wyjaśnił here, typ twojej klasy ogólnej jest tracony w czasie wykonywania.

W odpowiedzi na pytania:

  1. Chyba masz rację, że Java implementuje typu skasowaniu włączyć kompatybilność z poprzednimi wersjami biuletynie.
  2. Nie Nie sądzę, że istnieje "mod".
  3. Nie ma żadnych obejść (typy są usuwane podczas kompilacji), ale można użyć odbicia.
  4. Zobacz poniżej.

myślę prostszym rozwiązaniem byłoby więc coś w tym rodzaju: „Dlaczego Java nie pozwalają Type Erase”

public class WorkingHandler implements EventHandler<EventObject> 
{ 
    public void handleEvent(EventObject event) 
    { 
     // handle event 
     if (event instanceof MouseEvent) 
      handleMouseEvent((MouseEvent) event); 
     ... 
    } 

    ... 

    private void handleMouseEvent(MouseEvent event) 
    { 
     // handle mice 
    } 
} 
2

Erasure typu jest ładne, ponieważ oznacza, że ​​JVM nie musi wiedzieć nic o rodzajach ogólnych. Oznacza to również, że nie ma wpływu na wydajność przy użyciu typów ogólnych.

Również twoje pojęcie o konieczności utrzymania zgodności binarnej jest na miejscu (jak wskazano w Type Erasure tutorial). Typ erasure pozwala na kod napisany przed Javą. Typy ogólne mogą bezproblemowo współdziałać z kodem Java napisanym przy użyciu Generics.

Co powiesz na zrobienie dwóch programów obsługi i dołączenie obu?

public class KeyHandler implements EventHandler<KeyEvent> 
{ 
    public void handleEvent(KeyEvent event) 
    { 
     //handle key event 
    } 
} 

public class MouseHandler implements EventHandler<MouseEvent> 
{ 
    public void handleEvent(MouseEvent event) 
    { 
     //handle mouse event 
    } 
} 
5

Jedną z opcji jest użycie GuavaEventBus odpowiedzieć zdarzenia do abonentów. Został specjalnie zaprojektowany, aby rozwiązać problem, przed którym obecnie mierzysz.

Dzięki niemu nie trzeba wdrożyć wszelkie interfejsy ... po prostu dostarczyć dwa @Subscribe metody tak:

@Subscribe 
public void handleKeyEvent(KeyEvent event) { ... } 

@Subscribe 
public void handleMouseEvent(MouseEvent event) { ... } 

Niektóre dodatkowa dokumentacja na nim jest dostępny na Guava wiki.

1
  1. Tak, typ wymazywania jest realizowany tak, że specyfikacja JVM nie trzeba zmienić, aby uruchomić nową wersję (jeden rodzajowych wykonawczego).

  2. Jak wskazano, wiele języków nie usuwa typu implment. Jeśli szukasz w ciągu Java, być może, ale nie jestem pewien - nie to nie będzie działać na standardowych JVMs właśnie ze względu na 1.

  3. Można zrobić rodzajowe obsługi zdarzenia:

.

public class GenericHandler implements EventHandler<EventObject> 
{ 
    public void handleEvent(EventObject event) 
    { 
    if (event instanceof MouseEvent) { 
     MouseEvent mouseEvent = (MouseEvent) event; 
     //handle mouse event 
    } else if (event instanceof KeyboardEvent) { 
     KeyboardEvent keyboardEvent = (KeyboardEvent) event; 
     //handle keyboard event 
    } 
    } 
} 

Nie najbardziej eleganckie, ale działa :)

+2

Możesz pozbyć się tego łańcucha "if instanceof ...", implementując wzór projektu Odwiedzającego i podwójną wysyłkę. –

Powiązane problemy