出于显而易见的原因,我们不能直接实例化一个抽象类:
AbstractObj obj = new AbstractObj();
其中AbstractObj是一个类的形式:
public abstract class AbstractObj {
//... Body omitted
}
但是,如果我们有扩展类,如下所示:
public class ConcreteObj extends AbstractObj {
//... Body omitted
}
public class AnotherObj extends AbstractObj {
//... Body omitted
}
是否可以通过以下方式实例化对象?这根据传入的变量的类确定必须使用哪个构造函数。现在假设o1和o2保证属于同一类型。
protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2){
AbstractObj delta = ...?
}
例如,在上面,如果o1是ConcreteObj类型,有没有办法在运行时识别它是否属于这种类型并使用适当的构造函数?
这里 :
protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2){
AbstractObj delta = ...?
}
你可以用o1
获得具体的o1.getClass()
类。然后,如果此具体类具有默认构造函数,则可以使用Class.newInstance()
调用它:
protected AbstractObj computeDiff(AbstractObj o1, AbstractObj o2) throws IllegalAccessException, InstantiationException{
AbstractObj delta = o1.getClass().newInstance();
}
您可以使用instanceof语句。您可以将o1转换为ConcreteObj并使用此类的方法或字段。
if(o1 instanceof ConcreteObj){
//((ConcreteObj)o1).someMethod();
}
这绝对是代码味道。不要使用instanceof。不要使用反射。
绝对不要继续这条道路。
您的所有AbstractObj
实例都实现了一组通用操作。由于您的computeDiff
在AbstractObjs上运行,因此它不能依赖于它接收的不同实施的任何特殊功能。
因此,只要它们都遵循AbstractObj定义,方法接收或返回的对象类型无关紧要。如果需要,可以返回扩展AbstractObj的匿名类或任何其他子类。您甚至可以为此目的创建特定的子类。但无论你返回什么,它都不能返回任何比AbstractObj更多的东西。
将参数和返回值声明为AbstractObj
是您与任何调用方法的人签订的合同。不要破坏你的合同。