1

Folks, this seems like it should be straightforward, but I'm drawing a blank here.

As a simplified example, consider an abstract class called Number with an abstract method add(). I want to create two concrete subclasses, Integer and Float, with method signatures Integer.add(Integer other) and Float.add(Float other). A Float can NOT be added to an Integer. What should the method signature of the abstract add() method in the Number class be in order to enforce this constraint at compile-time?

3
  • 7
    generics: interface Num<T>{ T add(T); } Jun 20, 2013 at 3:30
  • 1
    I honestly do not think Java is the right language to be doing this sort of thing in
    – jk.
    Jun 21, 2013 at 7:17
  • I did end up using jozefg's solution... I have interface Number<T extends Number<T>>{ T add(T other); } And then with Float as class Float implements Number<Float> etc. The aim was ease of use for my library consumers, so while aviv's answer makes perfect sense, this is an example where usability trumps correctness. Thanks for the answers.
    – Der Poolie
    Jun 24, 2013 at 17:16

1 Answer 1

4

Number should not have an add() method.

Declaring a method in a base class (Or in an interface, for that matter), is a promise to implement this method. If your base class has add(Integer i), that's a promise that each instance of Number - be it a Float or an Integer - will have that method.

You can use generics, as jozefg commented - but then your two classes do not share a common superclass: Integer extends Number<Integer>, and Float extends Number<Float>. These are two different classes, that share their code. At runtime (In Java), erasure makes it look like it's the same class, but that's a technicality; When it comes to static (compile-time) terms, the two classes are distinct.

Another dynamic solution is to have Number define either add(Number), or both add(Integer) and add(Float), and throw an exception when the wrong method is invoked; This is certainly not what you're after, and is not generally considered a good use of Object-Oriented features.

2
  • My background is C#, but if you really need them to share the same superclass, couldn't you have Number<T> extends Number and have a separate Number base with anything that can be untyped in there?
    – Bobson
    Jun 20, 2013 at 23:11
  • You could (almost), but the base Number would not have the add() method. The middle-level, Number<T> would be two different (compile-time, and in C#, runtime too) classes. (Almost: In java, they can't both be named Number, because of the way generics are implemented).
    – aviv
    Jun 21, 2013 at 2:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.