Reputation: 8057
Seems that enum class already has a final
compareTo function, which cannnot be overriden. But my requirement is to customize an enum class like this:
enum Operator {
Add('+', 1),
Sub('-', 1),
Mul('*', 2),
Div('/', 2);
private char op;
private int priority;
private Operator(char _op, int _priority) {
op = _op;
priority = _priority;
}
}
Then I wish to have it implements Comparable interface to have the ability to compare among Add
, Sub
, Mul
, etc. But seems I cannot use implements Comparable<Operator>
as described above, javac gives compilation error:
Redundant superinterface Comparable<Operator> for the type Operator, already defined by Enum<Operator>Java(16777547)
So how to achieve my goal? Thanks.
Upvotes: 0
Views: 762
Reputation: 29028
Then I wish to have it implements
Comparable
interface to have the ability to compare amongAdd
,Sub
,Mul
, etc
You can't change the implementation of Comparable
in your enum.
Every enum implicitly implements Comparable
because its parent java.lang.Enum
has implemented this interface and method compareTo()
is marked with final
modifier, i.e. you can't override it.
Here is the quote from the Javadoc:
public final int compareTo(E o)
Compares this enum with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Enum constants are only comparable to other enum constants of the same enum type. The natural order implemented by this method is the order in which the constants are declared.
You can define a Comparator
implemented based on the priority
property as public static
field.
enum Operator {
MUL('*', 1),
DIV('/', 1),
ADD('+', 2),
SUB('-', 2);
public static final Comparator<Operator> BY_PRIORITY =
Comparator.comparing(Operator::getPriority);
private char op;
private int priority;
Operator(char op, int priority) {
this.op = op;
this.priority = priority;
}
public char getOp() {
return op;
}
public int getPriority() {
return priority;
}
}
If you need the order to reflect the standard order of arithmetic operations: Multiplication/Division comes before Addition/Subtraction, then the value of priority
of the MUL
and DIV
needs to be lower than the value of priority
of ADD
and SUB
.
The names of enum-member Add
, Sub
, etc., as well as names of constructor parameters _op
, _priority
in your code are not aligned with the Java naming convention.
Upvotes: 0
Reputation: 522
As you noted correctly, you cannot override the compare function of the enum class, because it is final.
The method is final, because of the semantics of an enum (Enumerated). It represent a number of values that could be completely substituted with there "ordnial" value. Actually, most applications of enum work with the ordinal value only. The names are just to make it easier to handle them.
Thus, the natural sort order (that is defined by the comparable interface) is to order by Ordinals and not on some field values. Actually, most enums don't have fields at all.
So if you find your self in a spot where you need to order enums based on something other than there ordinals, you should probably reconsider using enums ...
I'm going out an a limb here, since you didn't exactly specify what your final goal here is, but in most cases someone tries to implement Comparable, they try to sort a List or Array.
If that is the case, you could just work around that issue using a Comparator. Both the Array.sort, Collections.sort and Stream.sorted method have a overload that accepts a Comperator to define the sort order.
So what you could do is add a method to your enum like
public static int comparePrio(Operator first, Operator second) {
return Integer.compare(first.priority, second.priority);
}
and then call the sort method like this:
Collections.sort(myListOfValues, Operator::comparePrio);
(Code for Arrays and Streams is analog)
Warning: The code is not null save. If null is a possibility, you need to add additional null checks in your comparePrio method
Upvotes: 0
Reputation: 126
You can always declare Comparator.comparingInt(Operator::getPriority)
and use it to compare your operators.
Upvotes: 0