tags:

views:

138

answers:

5

In Java, is there any way to create an instance of any class that extends abstract class A, inside a member method of class A? Classes that extends abstract class A will return their instances with this method, but i don't want to implement same method in all subclasses with a "return this();" kind line.

EDIT: Ok sorry for the short explanation. In my application, there is an interface called Application, and it has a getInstance() method that returns an Application type. There is an abstract class called AbstractApplication which is a convenience class for Application interface for implementation, but only the interface is exposed in other apps. In some other apps, there will be a lookup for application objects, and this lookup will return an Application type (interface), not a specific implementation. Now here's my question; is there a way to implement getInstance() in AbstractApplication class so subclasses does not need to implement this method?

+4  A: 

If a superclass knows about its subclasses, this points to poor design.

The normal way of achieving something like this is to have a protected abstract method which subclasses must implement to return a subclass-specific result.

dty
This. You probably want to use the template method pattern instead: http://en.wikipedia.org/wiki/Template_method_pattern
Mike Daniels
Is not *the superclass knowing its subclasses* but letting the factory be specified at runtime. Like in the prototype design pattern.
OscarRyz
A: 

You can do it, but only with hackery. I'm sure other people will give details.

It's a bit of an odd design. You shouldn't really care about specific implementations - stick to the interfaces. The best you can do without changing the design much is:

protected abstract A createCompatibleInstance();

Have subclasses implement it.

But yuck.

Tom Hawtin - tackline
A: 

Something like this?

 abstract class Abs{
    public <T extends Abs> T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException {
        return clazz.newInstance();
    }
 }

Though this does not guarantee you'll get an instance of the class you're calling it from. To do that you'd still have to do something like:

class Abs1 extends Abs {
    public Abs1 getInstance() { return super.getInstance(Abs1.class) }
}

so not much of an improvement there.

I think the conclusion here is you'll end up with a lot less code and a lot less headaches if you just declare the method abstract in the parent, and implement it with new WhateverClassImIn() in every class that extends it. You can (probably) do it the way you want to, but it's not gonna be worth the effort.

Andrei Fierbinteanu
+1  A: 

I'm a bit rusty on my Java, but I believe that reflectively code executing in the super-class (in this example class A) will think it's part of the subclass.

Example:

public abstract class A
{
   public abstract void Something();
   public A Create()
   {
       Class me = this.getType(); // Returns a Reflective "Class" object for the SUB-Type
       // Use this object to reflectively instantiate a new instance, cast it as an A
       object obj = ReflectiveInstantiationHere(ItsBeenAWhile, SoGoogleThisPlease);

       return (A)obj;
   }
}

public class B extends A
{
   public void Something() 
   {
      A newInstanceOfB = Create();
   }
}

You can cast the returned value from A into a B later after checking types of course :)

Aren
+1  A: 

Yeap. That's pretty easy ( unless I misunderstood )

You have to use the Prototype design pattern ( or a variation of it that I show here )

It is useful when you don't know what the factory class could be until runtime. Unlike AbstractFactory where you can have different subclasses creating new types but you may pick one based on certain conditions.

With prototype you may simple get the "original" object ( the prototype ) injected into your application ( by virtue of a full futured Dependency Injection framework or by a simple class name ) and then create new instances of it.

Here's a sample code showing how to do this with a variation ( not using clone but newInstance method )

public abstract class Application {
    public Application newInstance() {
        try {
            return this.getClass().newInstance();//this creates an instance of the subclass 
        } catch( InstantiationException ie ){
            throw new RuntimeException( ie );
        } catch( IllegalAccessException iae ){
            throw new RuntimeException( iae );
        }
    }
    public String toString() {
        return "This is the class named: \""+ this.getClass().getSimpleName()+"\"";
    }
} 
// subclasses doesn't repeat the creation part
// they just have to override specific methods. 
class FirstClass extends Application {}
class SecondClass extends Application {}
class ThirdClass extends Application {}

And the rest of your code may program to the Application interface:

public void doSomethingWith( Application application ) {
        System.out.println( application.toString() );
}
public void startApplication( Application app ) {
    // etc etc 
}

Whenever you need a new instance you just call:

Application newApp = original.newInstance();

And that would create the correct type.

As you see the subclasses doesn't specify how to create new subclasses, that's all in the base class.

Invoking the method newInstance will always create a new instance which of the same type.

OscarRyz
this is exactly what i wanted, thank you!
Deniz Acay
Hmm... still smells of a horrible design bug to me. Also, relies on every subclass having a no-args constructor.
dty
That's probably because we have ... *different* exposure to software development. But to be honest, this idea is not my idea at all. It is described in the book: *Design Patterns: Elements of Reusable Object-Oriented Software* The main problem it solves, is specifying the factory at runtime ( when you don't know what types of objects you'll create )
OscarRyz