Monday, 31 July 2006

Generics - why no <this>?

So, am I just misunderstanding the spec, or is there no way to easily specify that a method should return the type of the object you called the method on?

Consider this example - I want to write a whole heap of methods in an abstract superclass, but I want each method to return the type of the subclass:

public abstract class A {
  <this> withYear(int year) {
    // implementation
  }
}

public class B extends A {
}

B b = new B().withYear(2006);

But, there is no <this> part in generics. The closest I could get was to generify the whole type (A) based on its subclass (B). But thats not really what I want to do at all.

Am I missing something?

6 comments:

  1. You can change return types covariantly, like this:

    public abstract class A {
    A withYear(int year) {
    // implementation
    }
    }

    public class B extends A {
    B withYear(int year) {
    return super.withYear(year);
    }
    }

    B b = new B().withYear(2006);


    It's messy but it works.

    ReplyDelete
  2. Sorry to reply 3 times in a row, but after giving it some proper thought I don't understand how you can implement the method in the superclass and have it return an instance of the subclass?

    ReplyDelete
  3. If you used clone() in the body of the method then it could be done. Reflection might be another approach, though it would be a little messy.

    ReplyDelete
  4. I would think it is because there are no objects and no reference to "this" at compile time, which is the only place where generics exist

    ReplyDelete
  5. Stephen Colebourne1 August 2006 at 20:23

    BTW, in case it wasn't clear, I was using as a non-existant syntax for something I want to do:

    public abstract class A {
    public withYear(int year) {
    return withMillis(calculateMillisForYear(year));
    }
    protected abstract withMillis(long millis);
    }

    public class B extends A {
    protected B withMillis(long millis) {
    return new B(millis);
    }
    }

    This kind of approach is very useful for an abstract superclass of multiple immutable subclasses.

    ReplyDelete
  6. If you have to implement each method in the subclass, what's wrong with the covariant return type as suggested by Keith in the first post as you would have to write the method signature out in any case?

    My initial thought was that you wanted a concrete implementation in an abstract superclass so you didn't want to write out the methods again in each subclass.

    ReplyDelete