3

次の問題があります。

次のようなライブラリ クラス (変更できない) の静的メソッドがあります。

Loader.loadModel()

Model 型のオブジェクトを返します。

また、いくつかのメソッドといくつかのフィールドを Model に追加する ExtendedModel という Model のサブクラスも作成しました。

できない:

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

Java では、スーパークラスのオブジェクトをサブクラスに割り当てることができないためです。

しかし、私は疑問に思っていました: Loader.loadModel() によって返されたオブジェクトにメソッドとフィールドを追加できる最良の方法はどれですか?

4

5 に答える 5

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;
    }

}

もちろん、プロパティに直接アクセスする代わりにゲッターを使用することもできます。これは、他のクラス/オブジェクトでも簡単にソリューションを使用するのに役立ちます。唯一の重要なことは次のとおりです。

  1. デフォルトのコンストラクターを宣言します (パラメーターなし、またはパラメーターのセットと既知の数)。
  2. 「Model」から「ExtendedModel」または拡張したい任意のクラスにすべてのデータをコピーします。
于 2013-03-17T08:23:08.240 に答える
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 に答える
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 に答える
0

できません

これがオブジェクト指向プログラミングの仕組みです。追加機能を追加したい場合は、を受け取り、、、 ...などの目的の値を返す静的メソッドを含むヘルパークラスを記述します。Modelintdouble

于 2013-03-17T07:56:55.407 に答える