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