As pointed out here lambdas provide a quite elegant way of specifying behaviour for individual enum values.
Before Java 8 I would normally have implemented this as:
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();
}
}
Now I tend to use:
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);
}
}
This seems significantly more elegant.
I cannot think of a reason to override methods for a specific enum value now. So my question is, are there any good reasons to use method overrides in an enum
now or should a functional interface always be preferred?
Enums are exactly final inner classes that extends java. lang. Enum<E> . You cannot extend, override or inherit an enum .
The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.
We've learned that we can't create a subclass of an existing enum. However, an interface is extensible. Therefore, we can emulate extensible enums by implementing an interface.
Many people consider Enums as a code smell and an anti-pattern in OOPs. Certain books have also cited enums as a code smell, such as the following. In most cases, enums smell because it's frequently abused, but that doesn't mean that you have to avoid them. Enums can be a powerful tool in your arsenal if used properly.
If you look at this answer which summarizes the advantages of using lambda expression in this enum
scenario you might notice that these advantages all disappear in the pre-Java 8 variant. It’s neither more readable than the old specialized enum
variant nor does it improve the performance. Further, the interface BinaryOperator
doesn’t exist before Java 8 so it’s another class you would need to add to your codebase to follow this approach.
The main reason to use this delegation approach in pre-Java 8 code would be to ease the migration if you plan to switch to Java 8 soon.
Update to your updated question:
If you mainly focus on the Java 8 use case, I would recommend to always use the delegation approach when all enum
cases have a different behavior which still follows a similar pattern which can benefit from using lambda expressions, as it’s the case when implementing operators like in your example.
A counter-example would be an enum
where most of them share a common behavior that will be overridden for one or a few cases only. E.g.:
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());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With