0

I have a superclass method which returns itself(for builder pattern). This class has several subclasses , so I want to return a reference to actual(subclass) type of the object. Something like this:

class SuperClass {
   T someMethodThatDoesSameThingForAllSubclasses() {

    // blablbal
    return reference_of_actual_object;

  }

}

So that I can call other subclass methods from subclass reference without casting. Like this:

SubClass obj=new SubClass(); 
obj.someMethodThatDoesSameThingForAllSubclasses().someSubclassMethod();
//currently this gives compiler error.  because first method returns superclass reference and super class doesn't have     someSubclassMethod

Is this posible and does it make sense to try to do something like this?

lazyCoding
  • 481
  • 2
  • 5
  • 13

1 Answers1

4

There's no particularly nice way of doing this, that I'm aware of. The best I've seen is just to cast - which you can do once, of course:

public class Superclass<T extends Superclass<T>> {
    @SuppressWarnings("unchecked")
    private final T thisAsT = (T) this;

    T someMethodThatDoesSameThingForAllSubclasses() {
       return thisAsT;
    }
}

public class Subclass extends Superclass<Subclass> {
    Subclass subclassOnlyMethod() {
        return this;
    }
}

And then:

Subclass subclass = new Subclass().someMethodThatDoesSameThingForAllSubclasses()
                                  .subclassOnlyMethod();

It's horrible that the cast doesn't actually check anything due to type erasure, but that's the joy of Java generics :(

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This way I couldn't invoke the subclass method. compile error remains. Plus there also is problem with inner customexception class. this way compiler doesnt let the inheritene from Throwable. – lazyCoding May 20 '14 at 14:22
  • @user3354638: Well you haven't mentioned exceptions before - but the subclass should be fine, so long as you give it the right `T`. I'll show an example. – Jon Skeet May 20 '14 at 14:23
  • I added caller 'caster' methods to all subclasses. It is horrible but does the job for now. – lazyCoding May 20 '14 at 14:34
  • @user3354638: But why? The code I've given does the same sort of thing, but in one go. Do you mean you've got an *abstract* `caster` method in the superclass, which you then implement in each subclass? While that removes a *potentially* invalid cast, I don't think it has any practical benefit. – Jon Skeet May 20 '14 at 14:37
  • By the way this is SQL builder class. the superclass is Sql and subclasses are Select,Update etc.. and the method is 'where'. It returns a reference to Sql which makes builder pattern fail. – lazyCoding May 20 '14 at 14:37
  • @user3354638: Well make it return a reference to `T` instead - as per my code. It sounds like you didn't follow the code in my answer correctly. – Jon Skeet May 20 '14 at 14:40
  • I applied your aprouch but it didn’t seem to remove the need of casting. this how I call: `new Delete("test").where("id", "7")).run()` .. where method return Sql(super class) and it doesnt have run() method – lazyCoding May 20 '14 at 14:42
  • Your right. I was extending subclasses without type paremeters. Now, it works. And since type erasure is not that problem in my case this is perfect solution. Thank you. – lazyCoding May 20 '14 at 15:15