3

我有以下问题。

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

Loader.loadModel()

它返回一个模型类型的对象。

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

我不能做:

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

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

但是,我想知道:这是向 Loader.loadModel() 返回的对象添加方法和字段的最佳方式

4

5 回答 5

2

尽管您添加了一个新类,但您没有该类的新实例。为了能够使用模型的其他方法和字段,您需要有一个 ; 的实例ExtendedModel。返回“常规”的Loader.loadModel()实例Model,导致问题。

要扩展对象的功能,您需要编写一个包装类。包装器通常采用“基”类的对象,将基本功能委托给它,并添加自己的一些方法/变量:

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());
于 2013-03-17T08:09:02.963 回答
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;
}

我的“扩展模型”课程:

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”或您想要扩展的任何类。
于 2013-03-17T08:23:08.240 回答
0

你不能

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

于 2013-03-17T07:56:55.407 回答
0

你不能,但你可以做的是使用适配器模式,它只是另一个类,将具有原始对象类型的字段,然后你可以对该对象执行操作。

于 2013-03-17T08:19:00.947 回答
0

你可以试试这个。您的解决方案总是需要一种粗略的方法。

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

Model m = Loader.loadModel();

现在您的投射将起作用,如下所示。

ExtendedModel mx = (ExtendedModel) m;

这类似于在泛型之前发生的事情。在我上面显示的特定情况下允许向下转换。

于 2013-03-17T08:26:00.313 回答