我有一堆我无法改变的课程;所有这些类都有一个共同的祖先(除了Object之外),它声明并实现了它们的大部分属性和方法。
假设我们有一个这样的继承树(仅供参考):
class Vehicle
class Bicycle extends Vehicle
class Skateboard extends Vehicle
class Boat extends Vehicle
class Car extends Vehicle
class Aircraft extends Vehicle
class Jetplane extends Aircraft
class Helicopter extends Aircraft
...
class Truck extends Vehicle
...
虽然class Vehicle
实际上更像是一个抽象类(它不是真的,但它永远不会代表它自己实例化),偶尔会创建class Aircraft
的对象。
现在要点:对象可以具有不被类反映的相互关系。由于它是一大堆类,并且集合每隔一段时间就会发生变化,因此为每个实现缺失行为的类维护一个子类是不切实际的。
因此,我的方法是使用一个类作为上述类的包装器。 构造函数将相应对象的类作为参数,然后使用反射对其进行实例化。
class VehicleW
{
// fields
public boolean isInitialized=false;
private Vehicle fVehicle;
...
// constructors
public VehicleW(Class aClass, ...)
{
Class VehicleClass = Vehicle.class;
if (!VehicleClass.isAssignableFrom(aClass))
return;
// <the reflection magic here>
...
// and on success mark this object as usable
isInitialized=true;
}
}
没有参数的构造函数在这里没有意义。但是现在class Aircraft
及其子类想要一些额外的属性,所以我想我可以建立一个class AircraftW extends VehicleW
来处理它们。
然后修改如下:
// fields
private Aircraft fAircraft;
// constructors
public AircraftW(Class aClass, ...)
{
Class AircraftClass = AirCraft.class;
if (!AircraftClass.isAssignableFrom(aClass))
return;
// <the reflection magic here>
...
// and on success mark this object as usable
isInitialized=true;
}
但是这失败了,因为Java智能地插入了对祖先的无参数构造函数的调用,这是不存在的(并且没有意义,正如已经说过的那样)。
调用参数化的super()也没有意义,因为我初始化了class Vehicle
的字段。好的,我可以稍后在我的AircraftW()
中将该字段设置为null
,但这似乎不正确。
有解决方法吗?或者我采取了绝对错误的做法?我考虑过泛型,但我似乎无法找到使用它的观点。接口?我不是那么多Java专家,所以欢迎任何建议。
编辑(未解决(以避免术语已解决))以下,您会找到一个正常工作的程序。我不能把它作为一个答案,因为托马斯把我带到了这个代码......他的答案......我接受了解决方案......我看不出有什么问题。
谢谢托马斯指出我正确的方向。
对于持怀疑态度,这里是测试程序的完整源代码:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Vehicle { public Vehicle(){} }
class Bicycle extends Vehicle { public Bicycle(){} }
class Skateboard extends Vehicle { public Skateboard(){} }
class Boat extends Vehicle { public Boat(){} }
class Car extends Vehicle { public Car(){} }
class Aircraft extends Vehicle { public Aircraft(){} }
class Jetplane extends Aircraft { public Jetplane(){} }
class Helicopter extends Aircraft { public Helicopter(){} }
class Truck extends Vehicle { public Truck(){} }
class VehicleW
{
protected Vehicle fVehicle=null;
public boolean isInitialized=false;
public VehicleW(Class aClass)
{
if (checkVehicle(aClass))
if ((fVehicle=makeVehicle(aClass))!=null)
isInitialized=true;
}
protected boolean checkVehicle(Class aClass)
{
Class tClass = Vehicle.class;
return (tClass.isAssignableFrom(aClass));
}
protected Vehicle makeVehicle(Class aClass)
{
Vehicle tVehicle = null;
System.out.format("trying to create %s\n",aClass.toString());
Constructor c;
try
{
c=aClass.getConstructor();
}
catch(NoSuchMethodException e)
{
System.out.format(" no constructor found\n");
return null;
}
try
{
tVehicle=(Vehicle)c.newInstance();
}
catch(InvocationTargetException e)
{
System.out.println(e.toString());
}
catch(InstantiationException e)
{
System.out.println(e.toString());
}
catch(IllegalAccessException e)
{
System.out.println(e.toString());
}
return tVehicle;
}
public Vehicle getVehicle()
{
if (!isInitialized)
return null;
return fVehicle;
}
public Class getWClass()
{
if (!isInitialized)
return null;
return fVehicle.getClass();
}
}
class AircraftW extends VehicleW
{
public AircraftW(Class aClass)
{
super(aClass);
/*
Class tClass=Aircraft.class;
if (!tClass.isAssignableFrom(aClass))
return;
isInitialized=true;
*/
}
@Override
protected boolean checkVehicle(Class aClass)
{
Class tClass = Aircraft.class;
return (tClass.isAssignableFrom(aClass));
}
}
class program
{
public static void tellme(VehicleW vx)
{
String s = "failed";
if (vx.getVehicle()!=null)
s="succeeded";
System.out.format(" making %s for %s %s\n",
vx.getWClass(),vx.getClass(),s);
}
public static void main(String[] args)
{
VehicleW v1, v2, v3;
AircraftW a1, a2, a3;
v1=new VehicleW(Bicycle.class);
tellme(v1);
v2=new VehicleW(Boat.class);
tellme(v2);
v3=new VehicleW(Helicopter.class);
tellme(v3);
a1=new AircraftW(Helicopter.class);
tellme(a1);
a2=new AircraftW(Aircraft.class);
tellme(a2);
a3=new AircraftW(Truck.class);
tellme(a3);
return;
}
}
和输出:
trying to create class Bicycle
making class Bicycle for class VehicleW succeeded
trying to create class Boat
making class Boat for class VehicleW succeeded
trying to create class Helicopter
making class Helicopter for class VehicleW succeeded
trying to create class Helicopter
making class Helicopter for class AircraftW succeeded
trying to create class Aircraft
making class Aircraft for class AircraftW succeeded
making null for class AircraftW failed
答案 0 :(得分:0)
当子类无法用父类完全填充构造函数的契约时。然后在同一个地方存在设计缺陷。
问题/原因可能是子类无效作为子类,或者父类具有许多功能。
对于你的例子,很难说是什么违反了合同。但最好和最灵活的工作是接口。
您声称自己不是Java方面的专家。接口只是面向对象编程中的一个概念,以便您在该领域寻找任何您应该熟悉它们的载体。因此,您可以在此了解有关接口和软件设计的更多信息。
答案 1 :(得分:0)
这听起来很像工厂模式,所以你可能想看一下。
你基本上会做的是这样的事情:
class VehicleFactory {
public static Vehicle createAircraft( /*Aircraft specific parameters*/) {
//build and return Aircraft, you can call your reflection magic here
}
public static Vehicle createBoat( /*Boatspecific parameters*/) {
//build and return Boat, you can call your reflection magic here
}
}
此外,您可能希望查看构建器模式。
在您的方法中有几个问题:
最后一点的例子:
initialized
最后一部分也将用于使用因子或构建器模式。