Jump to content

Range

From EggeWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Martin Fowler has written about the [Range Base Pattern] for representing a range of values. Here's a generic base class I wrote in Java which has the same basic functionality. I usually subclass this and add type specific methods.

<geshi lang="java"> /**

* A generic range.  I would prefer to define this as Range<E extends Comparable<? super E>>,
* but then pre 1.5 types can't be used with this.
* Additionally, you run into hell when you have Base implements Comparable<Base> and want to have
* Derived extends Base.  Derived can't implement Comparable<Derived> because it's already defined differently
* in the base class.
*/

public class Range<E extends Comparable> {

   protected final E min;
   protected final E max;
   public Range(E min, E max) {
       GuardHelper.notNullMultiple(min, max);
       validate(min, max);
       this.min = min;
       this.max = max;
   }
   protected void validate(E min, E max) {
       if (min.compareTo(max) > 0) {
           throw new IllegalArgumentException(min + " < " + max);
       }
   }
   public boolean contains(E value) {
       return value != null && min.compareTo(value) <= 0
               && max.compareTo(value) >= 0;
   }
   public E getMinimum() {
       return min;
   }
   public E getMaximum() {
       return max;
   }
   public int hashCode() {
       return min.hashCode() + max.hashCode();
   }
   public boolean equals(Object o) {
       if (this == o) {
           return true;
       }
       if (o == null || getClass() != o.getClass()) {
           return false;
       }
       Range range = (Range) o;
       return max.equals(range.max) && min.equals(range.min);
   }


   @Override
   public String toString() {
       return min + ".." + max;
   }

} </geshi>

And of course the unit test <geshi lang="java"> public class RangeUnitTest extends UnitTestCase {

   public void testContains() {
       Range<Integer> range = new Range<Integer>(3, 5);
       assertFalse(range.contains(2));
       assertTrue(range.contains(3));
       assertTrue(range.contains(4));
       assertTrue(range.contains(5));
       assertFalse(range.contains(6));
   }
   public void testCtor() {
       try {
           new Range<Integer>(5, 3);
           failIfNoExceptionThrown();
       } catch (IllegalArgumentException e) {
           pass();
       }
   }

} </geshi>