扩展java中静态方法返回的对象

时间:2013-03-17 07:55:16

标签: java oop static subclass superclass

我有以下问题。

我有一个库类的静态方法(我无法改变),如下所示:

Loader.loadModel()

它返回Model类型的对象。

我还创建了一个名为ExtendedModel的Model的子类,它为Model添加了一些方法和一些字段。

我做不到:

ExtendedModel m = Loader.loadModel() //compiler error
ExtendedModel m = (ExtendedModel) Loader.loadModel() //ClassCastException at runtime

因为在Java中你不能将超类的对象分配给子类。

但是,我想知道:哪种方法和字段可以添加到Loader.loadModel()返回的对象中的最佳方式

5 个答案:

答案 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而不是直接访问属性。这将有助于您轻松地将解决方案与其他类/对象一起使用。唯一重要的事情是:

  1. 声明默认构造函数(没有或设置和已知数量的参数)。
  2. 将所有数据从“Model”复制到“ExtendedModel”或任何您想要扩展的类。

答案 2 :(得分:0)

你不能

这就是面向对象编程的工作原理。如果要添加任何其他功能,编写包含静态方法的辅助类,接受Model并返回一些所需的值,例如: intdouble,...

答案 3 :(得分:0)

你做不到,但是你可以做的是使用adapter pattern,它只是另一个具有原始对象类型的字段的类,然后你可以对该对象执行操作。

答案 4 :(得分:0)

你可以试试这个。您的解决方案始终需要粗略的方法。

让“Loader.loadModel()”返回“ExtendedModel”的实例,但返回对象将被设置为Model的引用。像这样:

Model m = Loader.loadModel();

现在你的演员会工作,如下所示。

ExtendedModel mx = (ExtendedModel) m;

这类似于泛型之前发生的事情。如上所示,在特定情况下允许向下转发。