1

I would like to create a method called increaseValue, which it's signature is as following:

public Size increaseValue(Size s)

Also I have the following statement:

protected enum Size {XS, S, M, L, XL}

I need to know, how can I make the method return correct value (i.e. XL when input is L... etc.) while not using Switch-Case statement ?

Thanks !

Batman
  • 1,244
  • 2
  • 14
  • 26

6 Answers6

6

You could assume they are in increasing ordinal() order. I would add this a method on Size.

protected enum Size {
    XS, S, M, L, XL;
    static final Size[] VALUES = values();
    public Size incrementSize() { return VALUES[ordinal()+1]; }
    public Size decrementSize() { return VALUES[ordinal()-1]; }
}

Note: I wouldn't assume that XS is after XL, but rather you get an error (though not a very clear one)

Note: every time you call values() it creates a new array. It has to do this because the array is mutable and you might change it. I highly recommend saving a copy and avoid calling values() each time.

You can make the error messages clearer by overriding those methods.

protected enum Size {
    XS {
        public Size decrementSize() { throw new UnsupportedOperationException("No smaller size"); }
    }, 
    S, 
    M, 
    L, 
    XL {
        public Size incrementSize() { throw new UnsupportedOperationException("No larger size"); }
    };
    static final Size[] VALUES = values();
    public Size incrementSize() { return VALUES[ordinal()+1]; }
    public Size decrementSize() { return VALUES[ordinal()-1]; }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    What happens when you call `decrementSize()` for `XS`. Wouldn't that result in an ArrayIndexOutOfBoundsException? –  Jan 03 '17 at 12:39
  • @a_horse_with_no_name yes, an error, you could add a more meaningful one, or a dummy value – Peter Lawrey Jan 03 '17 at 12:40
  • 2
    @a_horse_with_no_name have added a way to have a more meaningful error message without having to use a condition check. – Peter Lawrey Jan 03 '17 at 12:43
1

In good OO design you want to internalize such things. Meaning: you want to provide a method like "nextSize()" within that enum, like:

public enum Size {
  XS, ...;

 public Size nextSize() {
   switch (this) ...

In this situation, the values are probably "fixed"; but in other situations, you might later want to insert new constants; thus I prefer an explicit mapping here; instead of relying on calls to ordinal().

And as mentioned in the other answers: you need to define what largestSize().nextSize() means. It could throw an exception, or return null (baaad idea). Alternatively, that method could return Optional<Size>; to make it clear to the caller that this method doesn't always return a valid result.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • but ordinal will still be function even if a new constant will be added, isn't it ? – Batman Jan 03 '17 at 12:59
  • Sure. But it requires you to **write** down your constants in the order you want them to have. That is a subtle detail that a person that changes your enum 6 months later might not be aware of. "Huh, we need some constant Y in enum E" ... to forget that X should go here "X Y Z" and not "X Z Y". – GhostCat Jan 03 '17 at 13:06
1

Here's why you should not do it: if you perform arithmetic on your enum, you can end up with invalid values, for instance what would happen if you added one to XL?

Here's how you do it:

Size.values()[s.ordinal()+1]
lcsondes
  • 484
  • 4
  • 16
0
public Size increaseValue(Size s) {
   Size[] allValues = Size.values();
   var newOrdinal = s.ordinal() + 1;
   return (newOrdinal >= allValues.length) ? null) : allValues[newOrdinal];
}

public Size decreaseValue(Size s) {
   var newOrdinal = s.ordinal() - 1;
   return  (newOrdinal < 0) ? null : values()[newOrdinal];
}
cyanide
  • 3,885
  • 3
  • 25
  • 33
0

Try this:

public Size increaseValue(Size s) {
    return Size.values()[s.ordinal() + 1]
}
MarmiK
  • 5,639
  • 6
  • 40
  • 49
Vampire
  • 35,631
  • 4
  • 76
  • 102
0

You van modify this enum like this:

  protected enum Size {
   XS,(1) 
   S(2), 
   M(3), 
    L(4), 
    XL(5);

private int sizeNo;

 Size(int sizeNo) {this.sizeNo = sizeNo;} 


 Size getBySizeNo(int sizeNo){
     for(size : Size.values()) {
     if (sizeNo == size.getSizeNo() ) {
     return size;
} 
} 
   throw new IllegalArgumentException() ;
} 

public Size increaseValue(Size s){
       return getBySizeNo(s.getSizeNo() +1) ;
      } 
 }
Mateusz
  • 205
  • 1
  • 4
  • 11