简体   繁体   English

使用变量类实例化抽象类

[英]Instantiate abstract class using class of variable

For obvious reasons, we cannot instantiate an abstract class directly like so: 由于明显的原因,我们不能像这样直接实例化一个抽象类:

AbstractObj obj = new AbstractObj(); 

Where AbstractObj is a class of the form: 其中AbstractObj是以下形式的类:

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. 这根据传入的变量的类来确定必须使用哪个构造函数。现在假设o1和o2的类型相同。

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? 例如,在上面,如果o1是ConcreteObj类型,是否可以在运行时识别它是否为这种类型并使用适当的构造函数?

Here : 这里 :

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

You can get the concrete class of o1 with o1.getClass() . 您可以使用o1.getClass()获得o1的具体类。 Then, if this concrete class has a default constructor, you can call it with Class.newInstance() : 然后,如果此具体类具有默认构造函数,则可以使用Class.newInstance()进行调用:

protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2) throws IllegalAccessException, InstantiationException{
   AbstractObj delta = o1.getClass().newInstance();
}

You can use instanceof statement. 您可以使用instanceof语句。 You can cast o1 to ConcreteObj and use this class' methods or fields. 您可以将o1强制转换为ConcreteObj并使用此类的方法或字段。

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

This is definitely code smell. 这绝对是代码的味道。 Do not use instanceof. 不要使用instanceof。 Do not use reflection. 不要使用反射。

Absolutely do not continue on this path. 绝对不要继续这条路。

All your AbstractObj instances implement a common set of operations. 您的所有AbstractObj实例均实现一组通用操作。 Since your computeDiff operates on AbstractObjs, it must not depend on any special features of the different implmentations it receives. 由于您的computeDiff在AbstractObjs上运行,因此它不得依赖于其收到的不同实现的任何特殊功能。

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. 因此,方法接收或返回什么类型的对象都没有关系,只要它们都遵守AbstractObj定义即可。 You can return an anonymous class that extends AbstractObj if you want or any other subclass. 如果需要,可以返回扩展AbstractObj的匿名类,也可以返回任何其他子类。 You can even create a specific subclass for just this purpose. 您甚至可以为此目的创建一个特定的子类。 But whatever you return, it must not return anything more than AbstractObj. 但是无论您返回什么,它都只能返回AbstractObj。

Declaring the parameters and the return value as AbstractObj is a contract you sign with whoever calls your method. 将参数和返回值声明为AbstractObj是与任何调用您的方法的人签订的合同。 Don't break your contracts. 不要违约。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM