Referencing Subtypes in Generics

Tagged:  

I ran into a problem recently while programming in Java where I wanted to define an interface method that returned a generic type which was tied to the type of the implementing class. If that sounds a little long-winded, let me give an example...

Let's say we have a Thing interface that defines a method for getting a type token, public Class<T> getType(). The Thing interface has several implementers, MyThing, YourThing, HisThing, HerThing, and so on. How does one make sure that T is the right subtype in the interface, which has no "knowledge" of its implementers (the same could be said of any base class and subclass as well)? Actually, the answer was sitting right under my nose in the core java libraries themselves, in the Enum class, whose declaration looks like this:

public abstract class Enum<E extends Enum<E>>

The E generic type looks a little confusing at first, like a kind of recursive definition. But when you think about it, it makes perfect sense: E is a subclass of an Enum type that is generified with the type--what else?--E. And E must be the appropriate subtype in any implementing class. So getting back to our little example, I could now retrofit my Thing interface to look like:

public interface Thing<T extends Thing<T>> {
     public Class<T> getType();
}

Any implementer now simply references itself in the generic type declaration:

public class MyThing implements Thing<MyThing> {
     public Class<MyThing> getType() { ... }
}

Most programmers prefer to think of generics only in the context of collections. But this provides a good example of how generics can establish type relationships in ways that are not possible in more traditional OOP methodology.

An excellent example. Scala actually takes this even further than Java by allowing self-types. So not only can you have methods which return types dependent on the implementer, but can also do things like define `this` to be of a more specific type:

trait Thing[A <: Thing[A]] { this: A =>
  // now, `this` is of type A, *not* type `Thing`
}

And if self-types are unnecessary, you can make the whole pattern a little more syntactically-clean by using abstract types:

trait Thing {
  type A <: Thing

  def getType: Class[A]
}

Same effect, but the class signature is cleaner.

@Daniel,

Yes, Scala has probably one of the most sophisticated type systems I've seen in a language. Depending on your perspective, this can be a good thing or a bad thing...;-) If you are already dipping your toes into the waters of generics, though, this is definitely a good thing and it would be nice to see Java add support for self-types in generics.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre> <div> <blockquote> <object> <embed> <img> <param>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Copy the characters (respecting upper/lower case) from the image.