0

For obvious reasons, we cannot instantiate an abstract class directly like so:

AbstractObj obj = new AbstractObj(); 

Where AbstractObj is a class of the form:

public abstract class AbstractObj {
//... Body omitted 
}

However if we have extending classes, such as the following:

public class ConcreteObj extends AbstractObj {
//... Body omitted
}

public class AnotherObj extends AbstractObj {
//... Body omitted
}

Is it possible to instantiate an object in the following manner? This determines which constructor has to be used based on the class of the variable passed in. Assume for now that o1 and o2 are guaranteed to be of the same type.

protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2){
    AbstractObj delta = ...?
}

For example, in the above, if o1 is of type ConcreteObj, is there a way to recognise at runtime whether or not it is of this type and use the appropriate constructor?

13
  • 1
    you want to call a constructor after constructing the object? Commented Mar 12, 2019 at 10:41
  • 3
    You can do it with : o1.getClass(). Then, if it has a default constructor, you can call it with o1.getClass().newInstance(). Commented Mar 12, 2019 at 10:41
  • Abstract classes can not be instantiated but you can instantiate its concretions. Commented Mar 12, 2019 at 10:41
  • You can use instanceof to check whether o1 is indeed a ConcreteObj. Commented Mar 12, 2019 at 10:42
  • 3
    This kind of problem you're facing is usually a code smell. Commented Mar 12, 2019 at 11:01

3 Answers 3

1

Here :

protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2){
   AbstractObj delta = ...?
}

You can get the concrete class of o1 with o1.getClass(). Then, if this concrete class has a default constructor, you can call it with Class.newInstance() :

protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2) throws IllegalAccessException, InstantiationException{
   AbstractObj delta = o1.getClass().newInstance();
}
Sign up to request clarification or add additional context in comments.

2 Comments

This will work, but it does require that all subclasses of AbstractObj have a no-args constructor.
@Jesper Yes, it is often a requirement for classes dealing with reflection.
0

You can use instanceof statement. You can cast o1 to ConcreteObj and use this class' methods or fields.

if(o1 instanceof ConcreteObj){
  //((ConcreteObj)o1).someMethod();
}

Comments

0

This is definitely code smell. Do not use instanceof. Do not use reflection.

Absolutely do not continue on this path.

All your AbstractObj instances implement a common set of operations. Since your computeDiff operates on AbstractObjs, it must not depend on any special features of the different implmentations it receives.

Therefore it does not matter what type of an object the method receives or returns, as long as they all adhere to the AbstractObj definition. You can return an anonymous class that extends AbstractObj if you want or any other subclass. You can even create a specific subclass for just this purpose. But whatever you return, it must not return anything more than AbstractObj.

Declaring the parameters and the return value as AbstractObj is a contract you sign with whoever calls your method. Don't break your contracts.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.