I am writing a small library where I have some interface
providing a method where the return value should be in a specified range. How can I explicitly forbid users of my library who implement this method to return a value not in this range?
Something like this:
//Library
interface FavoriteNumber {
//returned value must lie between 0 and 10
double whatsYourFavoriteNumberBetweenZeroAndTen();
}
...
//Classes implemented by user of library
class ILikePi implements FavoriteNumber {
@Override
public double whatsYourFavoriteNumberBetweenZeroAndTen() {
return 3.141; //Should be allowed
}
}
...
class AnswerToLifeTheUniverseAndEverything implements FavoriteNumber {
@Override
public double whatsYourFavoriteNumberBetweenZeroAndTen() {
return 42; //Should be forbidden
}
}
I think I could write something like
class DoubleBetweenZeroAndTen {
private final double value;
DoubleBetweenZeroAndTen(double value) {
if (value < 0 || value > 10) {
throw new IllegalArgumentException("value must be between 0 and 10");
}
this.value = value;
}
double toDouble() {
return this.value;
}
}
and return this instead of the double
but this doesn't feel good enough, since it is a double
between 0 and 10 that you want to work with thereafter, and not a DoubleBetweenZeroAndTen
.
If it is not possible to forbid this explicitly, what is the best way to ensure the user won't violate it? (Right now, I have a notice in the javadoc.)
You can't explicitly forbid people who implement your interface from returning any double
value from the whatsYourFavoriteNumberBetweenZeroAndTen()
method.
You can only define the expected range of returned values in the Javadoc of the interface, as part of the contract defined by the interface. Assuming your library has classes that use implementations of that interface, these classes may throw an exception if that method returns a value that violates your stated contract.
This is a standard practice in the JDK - for example, the contract of Comparator
's compare()
method defines the expected behavior of all implementations, and not following the contract could lead to exceptions or unexpected results in JDK classes that use implementations of the interface (such as Collections.sort(List<T> list, Comparator<? super T> c)
, whose Javadoc states it may throw IllegalArgumentException (optional) if the comparator is found to violate the Comparator contract
).