This entry deals with defining abstract methods in Java enums and writing their behavior. (The one written in Effective Java 3rd edition is almost the same. Make a note of what you tried.)
Java enums allow you to define methods as well as values.
Pattern that defines only the value
enum Operator {
PLUS, SUBTRACT, MULTIPLY, DIVIDE, NONE
}
On the other hand, you can define a method for each value and write it as shown in the figure below.
enum Operator {
PLUS {
@Override
BigDecimal apply(@NonNull BigDecimal lhs, @NonNull BigDecimal rhs) {
return lhs.add(rhs);
}
},
SUBTRACT{
@Override
BigDecimal apply(@NonNull BigDecimal lhs, @NonNull BigDecimal rhs) {
return lhs.subtract(rhs);
}
},
MULTIPLY {
@Override
BigDecimal apply(@NonNull BigDecimal lhs, @NonNull BigDecimal rhs) {
return lhs.multiply(rhs);
}
},
DIVIDE {
@Override
BigDecimal apply(@NonNull BigDecimal lhs, @NonNull BigDecimal rhs) {
return lhs.divide(rhs, BigDecimal.ROUND_UNNECESSARY);//;
}
},
NONE {
// allow null for rhs
@Override
BigDecimal apply(@NonNull BigDecimal lhs, BigDecimal rhs) {
return lhs;
}
};
abstract BigDecimal apply(BigDecimal lhs, BigDecimal rhs);
}
In "abstract BigDecimal apply (BigDecimal lhs, BigDecimal rhs);" in enum, the method to be defined for all values is specified, and the method is overridden when each value is declared.
(Supplement) In the above source, "@NonNull" is one of annotations provided by lombok that implements Null check. is.
If you define an enum in the above form, for example, the following method
public synchronized BigDecimal pushEvalButton() {
var v = new BigDecimal(sb.toString());
switch(currentOperator) {
case PLUS: {
v = stack.add(getCurrentValue());
break;
}
case SUBTRACT: {
v = stack.subtract(getCurrentValue());
break;
}
case MULTIPLY: {
v = stack.multiply(getCurrentValue());
break;
}
case DIVIDE: {
v = stack.divide(getCurrentValue(), BigDecimal.ROUND_UNNECESSARY);//
break;
}
case NONE: {
return v;
}
default: {
throw new RuntimeException("Not defined.");
}
}
currentOperator = Operator.NONE;
replaceBuffer(v.toPlainString());
clearStack();
return v;
}
You can write clearly as follows.
public synchronized BigDecimal pushEvalButton() {
var v = new BigDecimal(sb.toString());
if(Operator.NONE == currentOperator) {
return v;
}
v = currentOperator.apply(stack, getCurrentValue());
currentOperator = Operator.NONE;
replaceBuffer(v.toPlainString());
clearStack();
return v;
}
Since the content has moved to the enum method, it is natural that the code is reduced from the original method, but I felt that the following are merits. --I was able to expel the default in the switch --By using enum methods in other places, the processing is put together in one place.
In this entry, I explained how to define abstract methods in Java enum and write their behaviors with an example.
See [This commit] on GitHub (https://github.com/hrkt/commandline-calculator/commit/47e7b05075c2bb632b9bdabdf044ab3b5cefdeee) for an example of the difference above.
Recommended Posts