Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question
7  
generics: interface Num<T>{ T add(T); } –  jozefg Jun 20 '13 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 '13 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 '13 at 17:16

1 Answer 1

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.

share|improve this answer
    
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 '13 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 '13 at 2:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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