Question

Suppose I have a base class B, and a derived class D. I wish to have a method foo() within my base class that returns a new object of whatever type the instance is. So, for example, if I call B.foo() it returns an object of type B, while if I call D.foo() it returns an object of type D; meanwhile, the implementation resides solely in the base class B.

Is this possible?

Was it helpful?

Solution

Don't. Make the "foo" method abstract.

abstract class B {
    public abstract B foo();
}

Or receive an abstract factory through the base class constructor:

abstract class B {
    private final BFactory factory;
    protected B(BFactory factory) {
        this.factory = factory;
    }
    public B foo() {
        return factory.create();
    }
}
interface BFactory {
    B create();
}

Add covariant return types and generics to taste.

OTHER TIPS

As long as each class has a default constructor:

    public B instance() throws Exception {
        return getClass().newInstance();
    }

Well, I could be off but I would assume that since "this" always refers to the current object, you could do something like

public B foo() {
    return this.getClass().newInstance();
}

or something along those lines? If you create an instance of D and then call d.foo() you should get an instance of D returned as a B. You could return it as a plain Object but you should be as specific as possible in this instance, I think.

Apart from the fact that I think there probably is a design flaw if you want to accomplish this, you could try the following approach.

In your question, you are using static (class) methods, B.foo(), D.foo(), this cannot be accomplished using inheritance because the static methods do not have a dynamic nature, they do not take part in the lookup system. So you don't have enough type information.

If you are using a member function foo() you could have the following construct:

public class B {
    public B foo()
    throws IllegalAccessException, InstantiationException {
        return this.getClass().newInstance();
    }
}

public class D  extends B{    
}

public class Test {
    public static final void main(String[] args)
    {
        try {
            System.out.println((new B()).foo());
            System.out.println((new D()).foo());
        } catch (IllegalAccessException e) {
            e.printStackTrace();  
        } catch (InstantiationException e) {
            e.printStackTrace();  
        }
    }
}

As the other answers say, you can use getClass().newInstance() if there is a no-argument constructor in each subclass (make sure to catch InstantiationException and IllegalAccessException).

If any of the constructors require arguments, you can either use reflection or (preferable in my view) define a method like getNewInstance() which you can override in the subclass only if needed.

e.g.

Thing foo() {
    Thing th = getNewInstance();
    // do some stuff with th
    return th;
}

Thing getNewInstance() {
    return getClass().newInstance();
}

Then getNewInstance() can be overridden only if you really need to, for subclasses that don't have the default constructor.

Thing getNewInstance() {
    return new BigThing(10, ThingSize.METRES);
}

I think this might be possible to do using reflection, i.e. in your superclass you have:

public ClassName getFoo() throws InstantiationException, IllegalAccessException
{
    return getClass().newInstance();
}

Where ClassName is the name of your base class.

You'll have to cast it wherever you want to use it though... I'm not sure this is really a great solution!

Edit: newInstance() type methods are usually static, and of course you won't have an idea of what the type of your subclass is with a static method.

I don't think there's any way of getting a static method to (dynamically) create an instance of a subclass.

@Rik

Well, the real problem is that I have a abstract base class Thing. And Thing has a method called getNextThing() which returns a new instance of Thing.

Then, I have a number of subclasses like BigThing, LittleThing, SomethingThing, and I don't want to keep rewriting the getNextThing() method for each of them. It seems wasteful, since they all do the same... thing.

Am I incorrect in my approach?

I'm not sure why you're trying to do what you're actually trying to do. Providing more of a context might let us give you more help.

public class B <X extends B>{

public X foo() throws InstantiationException, IllegalAccessException{
    return (X)this.getClass().newInstance();
}
}        
public class C extends B<C>{        

}

Let me offer you this piece of advice. The way CS classes tend to be taught is that professors are enamored with inheritance, but haven't figured out composition. I think What you might be looking for is composition. So instead of calling getNextThing on the Thing itself, maybe you should think about making Thing implement Iterable

This means you will just need to write an Iterator that can encapsulate the logic of getting the next thing, as it doesn't seem to fit into your inheritance model. Another advantage of this is that you get some nice syntactic devices out of this (enhanced for loop comprehension).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top