views:

166

answers:

3

Consider I have the following interface:

public interface A { public void b(); }

However I want each of the classes that implement it to have a different return type for the method b().

Examples:

public class C { 
  public C b() {} 
}

public class D { 
  public D b() {} 
}

How would I define my interface so that this was possible?

+9  A: 

If the return type must be the type of the class that implements the interface, then what you want is called an F-bounded type:

public interface A<T extends A<T>>{ public T b(); }

public class C implements A<C>{
  public C b() { ... }
}

public class D implements A<D>{
  public D b() { ... }
}
Matt McHenry
+! - Very nice. I learned something here. Thanks, Matt.
duffymo
off-topic: syntax like this is why I am doing my best to avoid creating generified API as much as possible.
dimitko
Good answer (and a great example of the power of generics), but this doesn't prevent the programmer from doing C implements A<D> (see my second answer).
Cam
+1  A: 

Generics.

public interface A<E>{
    public E b();
}

public class C implements A<C>{
    public C b(){
        return new C();
    }
}

public class D implements A<D>{
    public D b(){
        return new D();
    }
}

Search up generics for more details, but (very) basically, what's happening is that A leaves E's type up to the implementing clases (C and D).

So basically A doesn't know (and doesn't have to know) what E might be in any given implementation.

Cam
I like that one more than the one marked as "the" answer, because you don't have to rely on the fact that the implementors will actually include their class name in the generified declaration. Thumbs up from me on that one.
dimitko
Thanks. I posted a new answer which improves over this and the 'best answer' as well :)
Cam
+2  A: 

Since Java supports covariant return types (since Java 1.5), you can do:

public interface A { public Object b(); }
meriton
Not great. You want your interface to leave as little room for accidental misuse as possible. With a method like that, it would be very easy for the programer to make a mistake when implementing `A`.
Cam
The question did not explicitly specify any restrictions on the overriding types. Of course, if such restrictions exist, one should enforce them with the interface where feasible.
meriton