2015-02-02 6 views
6

Wie bereits erwähnt here lambdas bieten eine ziemlich elegante Möglichkeit, Verhalten für einzelne Enum-Werte angeben.Gibt es einen Grund, Methoden in enums in Java zu überschreiben 8

Bevor Java 8 Ich würde normalerweise umgesetzt haben dies als:

enum Operator { 
    TIMES { 
     public int operate(int n1, int n2) { 
      return n1 * n2; 
     } 
    }, 
    PLUS { 
     public int operate(int n1, int n2) { 
      return n1 + n2; 
     } 
    }; 

    public int operate(int n1, int n2) { 
     throw new AssertionError(); 
    }    
} 

Jetzt neige ich dazu verwenden:

enum Operator { 
    TIMES((n1, n2) -> n1 * n2), 
    PLUS((n1, n2) -> n1 + n2); 

    private final BinaryOperator<Integer> operation; 

    private Operator(BinaryOperator<Integer> operation) { 
     this.operation = operation; 
    } 

    public int operate(int n1, int n2) { 
     return operation.apply(n1, n2); 
    } 
} 

Das wesentlich elegantere scheint.

Ich kann mir jetzt keinen Grund vorstellen, Methoden für einen bestimmten Enum-Wert zu überschreiben. Also meine Frage ist, gibt es irgendwelche guten Gründe, Methodenüberschreibungen in einem enum jetzt zu verwenden oder sollte eine funktionale Schnittstelle immer bevorzugt werden?

+1

denke ich, dass 'public int operate' im ersten Code sein sollte ... –

+0

Sie viele Methoden haben könnten, sich gegenseitig in einem Enum Aufruf. Und ihre Signatur stimmt möglicherweise nicht mit einer der Standardfunktionsschnittstellen überein. Übrigens sollte Ihre Methode operate() in Ihrem ersten Snippet als abstrakt deklariert werden, anstatt eine Implementierung bereitzustellen. –

+0

Ein anderer Weg (in Ihrem speziellen Beispiel) wäre 'enum Operator implementiert BinaryOperator ' und implementieren Sie dann 'apply' direkt. –

Antwort

5

Wenn Sie this answer betrachten, die die Vorteile der Verwendung von Lambda-Ausdruck in diesem enum Szenario zusammenfasst, stellen Sie vielleicht fest, dass diese Vorteile alle in der Prä-Java 8-Variante verschwinden. Es ist weder lesbarer als die alte spezialisierte enum Variante noch verbessert es die Leistung. Außerdem existiert die interface BinaryOperator nicht vor Java 8, also ist es eine andere Klasse, die Sie Ihrer Codebase hinzufügen müssten, um diesem Ansatz zu folgen.

Der Hauptgrund für die Verwendung dieses Delegierungsansatzes in Pre-Java 8-Code wäre die Vereinfachung der Migration, wenn Sie in Kürze auf Java 8 umstellen möchten.


Update auf Ihre Frage aktualisiert:

Wenn Sie in erster Linie auf den Anwendungsfall Java 8 konzentrieren, würde ich empfehlen, immer die Delegation Ansatz zu verwenden, wenn alle enum Fälle ein anderes Verhalten haben, die eine ähnliche folgt noch Muster, das von der Verwendung von Lambda-Ausdrücken profitieren kann, wie es bei der Implementierung von Operatoren wie in Ihrem Beispiel der Fall ist. Ein Gegenbeispiel wäre ein enum, in dem die meisten von ihnen ein gemeinsames Verhalten teilen, das nur für einen oder wenige Fälle überschrieben wird. Z.B .:

enum Tokens { 
    FOO, BAR, BAZ, AND, A, LOT, MORE // etc … 

    /** Special Token End-Of-File */ 
    EOF { 
     @Override 
     public boolean matches(String input, int pos) { 
      return input.length()==pos; 
     } 
    }; 

    // all ordinary tokens have the same behavior 
    public boolean matches(String input, int pos) { 
     return input.length()-pos >= name().length() 
      && input.regionMatches(pos, name(), 0, name().length()); 
    } 
} 
+0

Danke dafür. Ich habe diese Antwort nicht gefunden, bevor ich das gepostet habe - ich kann wirklich nicht scheinen, in SO zu arbeiten! Nachdem ich gesagt habe, dass ich nicht sicher bin, ob du wirklich meine Frage beantwortest. Ich frage nicht, ob der neue Weg besser ist (ich glaube es ist), aber ob es irgendeinen Grund gibt, jemals Methoden in Enums zu überschreiben? – sprinter

+0

Ich habe die Frage bearbeitet, um ein bisschen deutlicher zu machen, was ich möchte. – sprinter

+0

Das ist eine vernünftige Antwort, aber Standardverhalten könnte genauso einfach mit einem leeren Konstruktor implementiert werden, der dem Feld ein Standard-Lambda zuweist. – sprinter

Verwandte Themen