Search code examples
javadesign-patternsreflectionabstract-classinstantiation

How to dynamically create an object for an abstract class without casting?


I have a abstract class in JAVA and few subclasses. I have a function that returns an instance of one of these subclasses. I don't want to check with few if...else to create an object based on the return type. need to do it dynamically at run time. this solution didn't help me
The ReplaceExpression is an overloaded function that return different subclasses.

 // Expression is abstract class, A and B is subclass\
 // this return me null because i did not make a new object for e1, I know a subclass of Expression
       
   

Expression e1 = ReplaceExpression(1);
Expression e2 = ReplaceExpression("a");

    
    public Expression ReplaceExpression(int i)
    {
    Return new A();
    }
    
    public Expression ReplaceExpression(String s)
    {
    Return new B();
    }

I can do it like this but i need cleaner solution:

if (ReplaceExpression(x).getClass().getSimpleName() == "A")
Expression e1 = new A();

So my question is: is there anyway I can instantiate a new subclass for my abstract class without hardcoding or casting? something like dynamically or reflection


Solution

  • If I understand you correctly, you can do this with reflection.

    Assume you have Param class and Expression class:

    abstract class Param {
        public abstract Class<? extends Expression> getTargetClass();
    }
    
    class Sub1 extends Param {
        @Override
        public Class<? extends Expression> getTargetClass() {
            return A.class;
        }
    }
    
    class Sub2 extends Param {
        @Override
        public Class<? extends Expression> getTargetClass() {
            return B.class;
        }
    }
    
    class A extends Expression {
        public A() {}
    }
    
    class B extends Expression {
        public B() {}
    }
    

    You need a method to tell you which class you want to create, such as getTargetClass.

    Then in your ReplaceExpression method:

    public Expression ReplaceExpression(Param x) throws Exception {        
        Class<? extends Expression> cls = x.getTargetClass();
        Constructor<? extends Expression> con = cls.getConstructor();
        return con.newInstance();
    }
    

    Although you can do this, it is NOT a good solution, just use if statement:

    public Expression ReplaceExpression(Param x) {
        if (x instanceof Sub1)
            return new A();
        if (x instanceof Sub2)
            return new B();
        return null;
    }
    

    UPDATE

    It looks like you want to create a new Expression according to the returned Expression. You can use reflection: (still, NOT recommended)

    Class<? extends Expression> cls = ReplaceExpression(x).getClass();
    Constructor<? extends Expression> con = cls.getConstructor();
    Expression e1 = con.newInstance();