我有以下问题。
我有一个库类的静态方法(我无法改变),如下所示:
Loader.loadModel()
它返回Model类型的对象。
我还创建了一个名为ExtendedModel的Model的子类,它为Model添加了一些方法和一些字段。
我做不到:
ExtendedModel m = Loader.loadModel() //compiler error
ExtendedModel m = (ExtendedModel) Loader.loadModel() //ClassCastException at runtime
因为在Java中你不能将超类的对象分配给子类。
但是,我想知道:哪种方法和字段可以添加到Loader.loadModel()返回的对象中的最佳方式
答案 0 :(得分:2)
虽然您添加了一个新类,但您没有该类的新实例。为了能够使用模型的其他方法和字段,您需要具有ExtendedModel
的实例; Loader.loadModel()
会返回“常规”Model
的实例,从而导致问题。
要扩展对象的功能,需要编写包装类。包装器通常接受“base”类的对象,将基本功能委托给它,并添加一些自己的方法/变量:
public class ExtendedModel : Model {
private final Model wrapped;
public ExtendedModel(Model model) { wrapped = model; }
private int addedField = 123;
// Methods of the Model that you did not change simply forward the calls:
public void doSomething() { wrapped.doSomething(); }
public int calculateSomething() { return wrapped.calculateSomething(); }
// Extended methods do whatever you need them to do:
public int getAddedField() {return addedField;}
public void increment() {addedField++;}
}
现在您可以像这样创建ExtendedModel
的实例:
ExtendedModel m = new ExtendedModel(Loader.loadModel());
答案 1 :(得分:2)
您可以做的是使用Java Reflect API。这提供了最简单的实现,但可能没有其他解决方案那么快。
您基本上要做的是将所有数据从Model传递到ExtendedModel,然后让ExtendedModel扩展Model。
我的“模特”课程:
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Model model = new Model(1);
ExtendedModel extended = model.get(ExtendedModel.class);
extended.setA2("Hello World");
System.out.println(extended.getA1());
System.out.println(extended.getA2());
}
private int a1;
public Model() {}
public Model(int a1) {
this.a1 = a1;
}
public void setA1(int a1) {
this.a1 = a1;
}
public int getA1() {
return this.a1;
}
/**
* This method will transform the current object into an ExtendedModel.
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public <T> T get(Class<? extends T> classType) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
T object = classType.getConstructor().newInstance();
// pass all the data via setters
for (Field field : this.getClass().getDeclaredFields()) {
String methodName = "set"+StringUtil.ucfirst(field.getName()); // uppercase first!
classType.getMethod(methodName, field.getType()).invoke(object, field.get(this));
}
// return object
return object;
}
我的“ExtendedModel”类:
public class ExtendedModel extends Model {
private String a2;
public ExtendedModel() {}
public String getA2() {
return this.a2;
}
public void setA2(String a2) {
this.a2 = a2;
}
}
当然,您也可以使用getter而不是直接访问属性。这将有助于您轻松地将解决方案与其他类/对象一起使用。唯一重要的事情是:
答案 2 :(得分:0)
你不能。
这就是面向对象编程的工作原理。如果要添加任何其他功能,编写包含静态方法的辅助类,接受Model
并返回一些所需的值,例如: int
,double
,...
答案 3 :(得分:0)
你做不到,但是你可以做的是使用adapter pattern,它只是另一个具有原始对象类型的字段的类,然后你可以对该对象执行操作。
答案 4 :(得分:0)
你可以试试这个。您的解决方案始终需要粗略的方法。
让“Loader.loadModel()”返回“ExtendedModel”的实例,但返回对象将被设置为Model的引用。像这样:
Model m = Loader.loadModel();
现在你的演员会工作,如下所示。
ExtendedModel mx = (ExtendedModel) m;
这类似于泛型之前发生的事情。如上所示,在特定情况下允许向下转发。