1

Productという親オブジェクトのプロパティである子属性(ProductOptionおよびProductAttribute)のリストに追加する必要があります。3つのクラスはすべて、抽象クラスCMSを拡張します。

メソッド「attachChildToParent」を一般的に呼び出したいのですが、を延期instanceofしてProductにキャストすることにより、避けられないことを遅らせています。

キャストを避けるためにこれを一般的に書く方法はありますか?

テストする:

package puzzler;

import java.util.ArrayList;
import java.util.List;

public class Tester {
    public static void main(String[] args) {
        Product p = new Product();
        ProductAttribute pa = new ProductAttribute();
        ProductOffering po = new ProductOffering();

        List<ProductAttribute> lpa = new ArrayList<ProductAttribute>();
        List<ProductOffering> lpo = new ArrayList<ProductOffering>();

        attachChildToParent(lpa, p);
    }

    static void attachChildToParent(List<? extends CMS> listChild, Product parent) {
        for (CMS cmsItem : listChild) {
            parent.attach(cmsItem);         
        }
    }
}

製品クラス(親)

package puzzler;

import java.util.List;

abstract class CMS {
    String node;
}
public class Product extends CMS {
    List<ProductAttribute> lpa;
    List<ProductOffering> lpo;

    public List<ProductAttribute> getLpa() {
        return lpa;
    }

    public void setLpa(List<ProductAttribute> lpa) {
        this.lpa = lpa;
    }

    public List<ProductOffering> getLpo() {
        return lpo;
    }

    public void setLpo(List<ProductOffering> lpo) {
        this.lpo = lpo;
    }

    public void attach(ProductAttribute childNode) {
        this.getLpa().add(childNode);
    }

    public void attach(ProductOffering childNode) {
        this.getLpo().add(childNode);
    }

    //  I want to avoid this.  Defeats the purpose of generics.
    public void attach(CMS cms) {
        if (cms instanceof ProductOffering) {
            this.getLpo().add((ProductOffering) cms);
        } else         {
            if (cms instanceof ProductAttribute) {
                this.getLpa().add((ProductAttribute) cms);
            }
        }
    }
}

子クラス1

package puzzler;

import puzzler.CMS;

public class ProductAttribute extends CMS {
    String node;

    public String getNode() {
        return node;
    }

    public void setNode(String node) {
        this.node = node;
    }
}

子クラス2

package puzzler;

import puzzler.CMS;

public class ProductOffering extends CMS {
    String node;

    public String getNode() {
        return node;
    }

    public void setNode(String node) {
        this.node = node;
    }
}
4

5 に答える 5

5

ビジターパターンを使用してキャストを回避できます。CMSクラスで、新しい(抽象)メソッドを追加しますattachTo(Product parent)。各サブクラスで、このメソッドを実装して親でattachを呼び出すことができ、適切な関数が解決されます。

于 2012-08-17T12:31:09.237 に答える
2

サブクラスに委任します。

public void attach(CMS cms) {
    cms.callAdd(this);

}

CMSで追加:

public abstract void callAdd(Product product);

そしてProductOfferingに追加:

public void callAdd(Product product) {
   getLpo().add(this)       
}

ProductAttributeについても同様です...

于 2012-08-17T12:35:38.263 に答える
0

オーバーライド?

public void attach(ProductOffering cms) {
   this.getLpo().add(cms);
}

public void attach(ProductAttribute cms) {
   this.getLpa().add(cms);
}
于 2012-08-17T12:33:36.477 に答える
0

これを回避する方法はありますが、ジェネリックでは回避できません。ジェネリックスを使用すると、キャストを回避できるコードを記述できますが、を回避する必要がある場合は役に立ちませんinstanceof。主な理由は、ジェネリック型のすべての変数がObject内部として扱われることです。

そして、これが、コンパイラがattach(CMS)から呼び出すときに汎用メソッドを使用する理由ですattachChildToParent()。アタッチする子のタイプは次のようになります。CMSコンパイラが、を呼び出すときに使用するタイプを保持する方法はありませんattachChildToParent()

唯一の解決策は、子にattachメソッドを作成することです。

public class ProductAttribute extends CMS {
    @Override
    public void attachTo( Product p ) {
        p.getLpo().add( this );
    }
}
于 2012-08-17T12:35:39.300 に答える
0

ジェネリックはあなたの問題を解決することはできません。その後、インスタンス固有の情報を失うため<? extends CMS>、リスト内のすべての要素はの子CMSのみになります。

あなたのデザインに適合し、あなたの問題を解決するパラメータとして両方のリストを取り、それが効率的である簡単な方法を追加してみませんか

public void attach(List<ProductAttribute> lpa, List<ProductOffering> lpo) {
    this.lpa.addAll(lpa);
    this.lpo.addAll(lpo);
}
于 2012-08-17T13:08:28.887 に答える