0

As far as I know, declaring an interface is like so:

public interface Roots_Squares {
    public double square_root( double value );
}

Now... how do you enforce value to have non-negative values? Such a function should avoid negative values right? If someone creates a class that implements this, and that implementation does not handle negative values, and then I use their class with a negative value... well, things break.

It then becomes my responsibility to check for negatives when I'm pretty sure the implementor should do the checking.

user2738698
  • 957
  • 1
  • 8
  • 20
  • 1
    What Java version? Java 8 has the possibility for code such as `Arrays::<@NonNegative Integer>sort` with things such as https://code.google.com/p/jsr-305/source/browse/trunk/ri/src/main/java/javax/annotation/Nonnegative.java?r=46 –  Apr 04 '14 at 19:19
  • @MichaelT: The code that you cite is part of sample code for a JSR that is still very early in the implementation stages (creation of the expert group). It does not seem to have been implemented as part of Java 8. – jhominal Apr 04 '14 at 19:27
  • @jhominal Being an JEE guy, I'm stuck *way* behind the curve and just glance at the new things I'll get in a few years... http://types.cs.washington.edu/jsr308/specification/java-annotation-design.html seems to be more appropriate that was mentioned in http://www.mscharhag.com/2014/02/java-8-type-annotations.html –  Apr 04 '14 at 19:32
  • possible duplicate of [Necessity of Interfaces for Small Projects](http://programmers.stackexchange.com/questions/234837/necessity-of-interfaces-for-small-projects) – gnat Nov 30 '14 at 09:23

4 Answers4

3

As explained a bit more thoroughly in this answer, that's (part of the) price you pay for an interface. If you want to be able to use new implementations of your abstraction at any time, you have no way of forcing those implementations to be correct.

Doval
  • 15,347
  • 3
  • 43
  • 58
  • There is, of course, validation. Granted, you have to implement that in the class, not the interface. – Robert Harvey Apr 04 '14 at 19:20
  • @RobertHarvey But someone always has the option of not using your class and producing a totally new and bogus instance of the interface. – Doval Apr 04 '14 at 19:22
  • So how about, instead of double, a custom, non-negative derived class of doubles? So the function becomes "public double square_root( Positive_Double value );" or would that be too much of stretch? – user2738698 Apr 04 '14 at 19:29
  • @user2738698 There's a couple of issues. 1) I wouldn't make it a subclass of the double class because it doesn't behave like a double. Particularly, doubles are closed under subtraction - subtracting two doubles results in another double. For positive doubles though, 3.0 - 5.0 blows up because -2.0 is not a positive value. – Doval Apr 04 '14 at 19:37
  • @user2738698 2) Performing a runtime check in `PositiveDouble`'s constructor ensures that you end up with a valid argument, but you still can't force the implementors to implement your interface correctly. They could just as easily implement `square_root` to always return `0.0`, loop forever, or throw an exception. – Doval Apr 04 '14 at 19:39
  • @user2738698 3) If you place compile time restrictions on `PositiveDouble` (e.g. make the constructor private and only provide a few initial `PositiveDouble` values and only safe ways of combining them, e.g. addition) you make sure a negative double is never produced but also rule out a ton of programs that would be correct too. There's no mechanical way to ensure a program won't generate a negative number during the course of its execution without actually executing it. – Doval Apr 04 '14 at 19:43
  • In terms of creating a Square_Rootable class with the method square_root, it can be overriden too huh? – user2738698 Apr 04 '14 at 19:45
  • @user2738698 You can make the method `static` since I imagine it only depends on the argument. You can also make the class `final` which prevents subclassing, or if you need subclassing for some reason you can mark that particular method `final`. – Doval Apr 04 '14 at 20:03
  • 2
    "There's no mechanical way to ensure a program won't generate a negative number during the course of its execution without actually executing it." – Only if the language is Turing-complete. In dependently-typed languages, types such as "non-negative integer" or "list of length `n`, where `n` is a *runtime* value" can be expressed, and can be *statically* type-checked. – Jörg W Mittag Apr 05 '14 at 00:32
  • +1 Even adding `throws IllegalArgumentException` to the method signature wouldn't enforce anything. – Tulains Córdova Nov 26 '14 at 21:27
0

The comments on Doval's answer are right: create and use a PositiveDouble. Also, consider using a design by contract tool. A design by contract tool like cofoja might solve your problem. I have not used 1 but I know that there are several design by contract tools in Java.

jgleoj23
  • 107
  • 2
  • The other comments are right, however, in that there is no realistic way of creating such a type in a traditional object-oriented language like Java. It requires much better type inference than is available in such languages in order to not be a nightmare to use such a type. – Jules Nov 27 '14 at 07:58
0

Your interface should document how it handles bogus input, and can declare Exceptions it will throw. In this case, a simple

@throws IllegalArgumentException would do the trick.

user949300
  • 8,679
  • 2
  • 26
  • 35
-1

Doval's answer is outdated now. You can use an enforce parameter properties(check arguments) in the interface:

public interface Math {
    /**
     * @throws IllegalArgumentException if value <= 0
     */
    default public void sqrt(Double value) {
        if(value <= 0) throw new IllegalArgumentException("value must be greater than 0");
        squareRoot(value);
    }

    public void squareRoot(Double value);
}
jgleoj23
  • 107
  • 2
  • Programmers is [about](http://programmers.stackexchange.com/tour) conceptual questions and answers are expected to explain things. Throwing code dumps instead of explanation is like copying code from IDE to whiteboard: it may look familiar and even sometimes be understandable, but it feels weird... just weird. [Whiteboard doesn't have compiler](http://stackoverflow.com/q/5508110/839601) – gnat Dec 02 '14 at 21:29