web-dev-qa-db-ja.com

java、SuperClassからSubClassを初期化します

public class Base {
  //long list of attributes
  // no Constructor using fields
  // no init methode 
  // i cannot change this class
}

今私は次のように基本クラスを拡張しました:

public class subClass extends Base{
   private boolean selected;

   ...
   getter und setter
   ...
}

ベースオブジェクトのリストになりますList<Base>

しかし、私は同じリストが必要ですが、List<SubClass>基本クラスからサブクラスを初期化する方法はありますか?

例:

for(Base b: list){
   SubClass sub = (SubClass)b; // Thats wrong i know
   if(...){
       sub.setSelected(true);
   }
   newList.add(sub);
}

ベースClassの各属性がサブクラスに手動で初期化されるのを避けようとしています

コメントで要求されたとおりに質問を更新します。上記のデザインは単なる例です。私のQUESTINは正確に:

baseClassをSubClassに変換する理由(sence Subclass extends BaseClass) 不可能である?なぜJavaは、次のことを許可しません:

例:

Class Base{
   private String name;
.....
}
Class SubClass extends Base{
   private String title;
}

その後

Base b = DBController.getById(...);
SubClass sub = (SubClass)b; 

その後、オブジェクトsubにはオブジェクトbの属性名が必要であり、title属性はnullです。

なぜこれはJavaには当てはまらないのですか?

私の悪い英語でごめんなさい、ありがとう

11
Rami.Q

List<Base>がある場合、それをList<SubClass>に変換することはできません。これは主に、リストにSubClassのインスタンスが含まれていない可能性があるためです。あなたができる最善のことは:

List<SubClass> newList = new List<SubClass>();
for(Base b: list){
    if (b instanceof SubClass) {
        SubClass sub = (SubClass)b;
        . . .
        newList.add(sub);
    }
}

しかし、一般的に、このようなことをしていることに気付いたときは、デザインに何か問題があります。 Baseをサブクラス化し、 代わりにcomposition を使用することは避けたい場合があります。

[〜#〜] edit [〜#〜]コメントに基づいて、SubClassのリストを作成したいようです。 Baseインスタンスのリストを開始として使用するインスタンス。 1つのアプローチは、引数としてSubClassをとるBaseのコンストラクターを定義することです。

public class SubClass extends Base{
    private boolean selected;

    public SubClass() {
        // default constructor
    }

    public SubClass(Base original) {
        // copy constructor -- initialize some fields from
        // values in original, others with default values
    }
    ...
    getter und setter
    ...
}

次に、次のコマンドを使用して新しいリストを作成できます。

List<SubClass> newList = new List<SubClass>();
for(Base b: list){
    SubClass sub = new SubClass(b);
    . . .
    newList.add(sub);
}
7
Ted Hopp

方法があります:さまざまなJava Beans仕様ベースの操作。

例えば:

Commons BeanUtils

for( Base base: list ){
   SubClass sub = new SubClass();
   PropertyUtilsBean.copyProperties( sub, base );
   if(...){
       sub.setSelected(true);
   }
   newList.add(sub);
}

これは、同じ名前のget/setterに基づいて機能します。内部フィールドをコピーしません。

内部フィールドをコピーする必要がある場合、実際にはjavax.lang.reflectを使用して実装するのはそれほど難しくありません。

3
Ondra Žižka

多くの属性を持つクラスがあり、それらすべてを簡単に設定する方法がないようです。これで、追加の属性を持つクラスが必要であるが、基本クラスのその混乱に対処する必要があるという問題が発生しました。

サブクラスを作成してキャストする代わりに、醜いクラスのラッパークラスを作成することをお勧めします。

public class BigDumbClass {
    // A lot of attributes
    // No Constructor
    // No init method
}

public class Wrapper {
    private BigDumbClass base;
    private boolean selected;

    public Wrapper(BigDumbClass base) {
        this.base = base;
        this.selected = false;
    }

    //getters and setters
}

これで、新しいリストを作成する必要があるときに、古いリストのすべてをラップできます。

List<BigDumbClass> oldList = someData();
List<Wrapper> wraps = aNewList();
for (BigDumbClass bigDumb : oldList) {
    Wrapper wrap = new Wrapper(bigDumb);
    if (someCondition()) {
        wrap.setSelected(true);
    }
    wraps.add(wrap);
}

理想的には、BigDumbClassは、Wrapperも実装できるインターフェイスを実装し、ラッパーがラップしたインスタンスへのすべての呼び出しを延期できるようにします。

public class BigDumbClass implements SharedInterface {
    // All the stuff outlined above
}

public class Wrapper implements SharedInterface {
    // All the stuff outlined above

    // Methods defined in SharedInterface
    public void doSomething() {
        base.doSomething();
    }
}

それ以外の場合は、インスタンスにゲッターを提供して直接アクセスできます。

BigDumbClass base = wrapper.getBase();
base.doSomething();
2
Jake Greene