6

Is it possible to have an enum change its value (from inside itself)? Maybe it's easier to understand what I mean with code:

enum Rate {
    VeryBad(1),
    Bad(2),
    Average(3),
    Good(4),
    Excellent(5);

    private int rate;

    private Rate(int rate) {
        this.rate = rate;
    }

        public void increateRating() {
            //is it possible to make the enum variable increase?
            //this is, if right now this enum has as value Average, after calling this
            //method to have it change to Good?
       }
}

This is want I wanna achieve:

Rate rate = Rate.Average;
System.out.println(rate); //prints Average;
rate.increaseRating();
System.out.println(rate); //prints Good

Thanks

devoured elysium
  • 101,373
  • 131
  • 340
  • 557

4 Answers4

11

Yes. You could simply call

rate = Rate.Good;

for this specific case. But what I think you are really looking for is a successor function.

Here you are:

public class EnumTest extends TestCase {
    private enum X {
        A, B, C;
        public X successor() {
                return values()[(ordinal() + 1) % values().length];
        }
    };

    public void testSuccessor() throws Exception {
        assertEquals(X.B, X.A.successor());
        assertEquals(X.C, X.B.successor());
        assertEquals(X.A, X.C.successor());
    }
}
Community
  • 1
  • 1
Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
  • + 1. This is probably the best way to go. Nice succinct code too. – Mark Bolusmjak Apr 15 '10 at 17:46
  • 1
    But... the `Rate` it self won't change is it? – OscarRyz Apr 15 '10 at 17:52
  • @Oscar I think the idea is that devoured would do something like `rate = rate.successor();` – AaronLS Apr 15 '10 at 17:56
  • 2
    In my example, just call `x = x.successor();` Yours would probably look more like `rate = rate.nextRating();` (depending, of course, on how you name the function). If you want to change the value of the enum itself - not a variable which holds the enum - no, that's not possible. – Carl Manaster Apr 15 '10 at 17:58
  • 1
    The only comment, in `successor()` method `values()` should probably be cached. It is called twice and the operation has a non-trivial cost. – Alexander Pogrebnyak Apr 15 '10 at 18:17
  • I'll +1 if you move your comment to the answer, for that's the real answer ***No, that's not possible, but you can etc. etc*** This alternative is really enlightening, but I can't upvote you because the systems says: *Vote to old to be changes, unless this answer is edited* :-D – OscarRyz Apr 15 '10 at 18:29
  • @Oscar Reyes I'm going to leave it as a comment. I *think* the OP's question is satisfactorily addressed by the answer itself, although it is ambiguous, and certainly possible that s/he really wanted this in the form of a void function. – Carl Manaster Apr 15 '10 at 18:34
  • Well the problem with your approach is that I can't do something like Rate rate = Rate.Good; like an enum would. – devoured elysium Apr 16 '10 at 07:38
  • @devoured elysium: yes, you can do exactly that. It's still 100% an enum. It's just that this lets you take an existing rate and - without checking its value - assign its successor. `Rate rate = Rate.Average; rate = rate.successor();` Simple as that. – Carl Manaster Apr 16 '10 at 14:21
  • Yes, I see your point. I had already implemented that. The problem is having to make rate = rate.sucessor(). I'd like to do instead just rate.sucessor(), but I guess it just isn't possible at all. – devoured elysium Apr 18 '10 at 21:52
2

Do you want something like this?

class Rate {
    private static enum RateValue {
        VeryBad(1),
        Bad(2),
        Average(3),
        Good(4),
        Excellent(5);

        private int rate;

        public RateValue(int rate) {
            this.rate = rate;
        }

        public RateValue nextRating() {
            switch (this) { /* ... */ }
        }
    }

    private RateValue value;

    public void increaseRating() {
        value = value.nextRating();
    }
}
Binil Thomas
  • 13,699
  • 10
  • 57
  • 70
2

The example in the question tries to change the value of "rate" by calling a method on it. This is impossible, enum values are objects, so you cannot change them for the same reasons you cannot assign a new value to "this". The closest thing you can do is add a method that returns another enum value, as proposed by Carl Manaster.

Kees Kist
  • 2,641
  • 5
  • 20
  • 25
-1

It should be possible but I have to admit that I've never tried it. In the end enums are just objects with a little twist so you should be able to do that unless you define the rate field as final.

ilikeorangutans
  • 1,753
  • 1
  • 11
  • 14