みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

JAVAの継承について

JavaでクラスA,B,Cがあり、A,BはクラスCを継承しています。

この時にAのインスタンスを生成しCにある変数に値を設定します。
この設定した情報をBのインスタンスに一気に設定することは可能でしょうか?

やりたいこととしてはAに設定した情報をBにコピーするようなイメージです。
すべてのsetterを呼びだして設定するのが面倒なので。

例)構文的に間違ってるかもしれませんがやりたいことは以下のような感じです。

A a = new A();
a.setStr("aaa");
a.setInt(5);

B b = new B();
b.setStr(a.getStr());
b.setInt(a.getInt();

class A extends C{}
class B extends C{}
class C {
 int x = 0;
 String str = "";

 private String setStr(String str){this.str=str;}
 private String setInt(int i){this.x=i;}
 private String getInt(){return this.x;}
 private String getStr(){return this.str;}
}

投稿日時 - 2010-12-17 00:18:11

QNo.6389432

困ってます

質問者が選んだベストアンサー

7の人への補足で、あなたのやりたいことが何となくわかってきましたよ。
継承にこだわるのであれば、リフレクションで以下のように解決できます。

public static void main(String[] args) throws Exception{
 A a = new A();
 a.setX(100);
 a.setY("きのこの山");
 a.setZ("たけのこの里");
 B b = new B();
 copyField(a, b);
 System.out.println(String.format("x:%d, y:%s, z:%s", b.getX(), b.getY(), b.getZ()));
}

private static void copyField(C a, C b) throws IllegalAccessException {
 Field[] fields = C.class.getDeclaredFields();
 for(Field f : fields) {
  f.set(b, f.get(a));
 }
}

もしくは、A/BとCの関係を継承ではなく委譲で解決すると
Cのインスタンスを普通にcopyするだけで済むのですよ。
こちらの方が汎用性があるのでわたしは好きです。

投稿日時 - 2010-12-22 00:32:57

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(8)

ANo.7

スーパークラスにコピー用のメソッド用意したら?

public class C {
private int x;
private int y;
public void assign(C src) {
this.x = src.x;
this.y = src.y;
}
public int getX() { return x };
public void setX(int x) { this.x = x };
public int getY() { return y };
public void setY(int y) { this.y = y };
}

public class A extends C {
}

public class B extends C {
}

A a = new A();
a.setX(1);
a.setY(2);
B b = new B();
b.assign(A);

投稿日時 - 2010-12-17 16:19:22

補足

質問内容に補足します。

・例としては設定する値は2つですが実際は100個くらいあります。
・例の実装方法でOKだがもっと簡単にやる方法はないかという質問になります。
・理由が分からない等の回答がありますが、例は分かりやすく簡略化したものであるため分かりにくくなってしまったかもしれません・・・

やりたいことは継承している情報のみを取りだして設定する方法になります。

投稿日時 - 2010-12-19 00:45:52

Observer パターンだな

参考URL:http://www.techscore.com/tech/DesignPattern/Observer.html

投稿日時 - 2010-12-17 14:23:40

ANo.5

リフレクションを使えば、クラスのメンバが取得できます。
for文で、メンバを順に抜き出し、Invokeでセッタ/ゲッタを
実行すれば目的のものができるでしょう。
クラスの定義が変更されても、この部分は修正不要です。

ユーティリティなどのように、パラメータのオブジェクト型が
特定できないメソッドではリフレクションによって、メンバの
名前や属性を調べて処理する例が結構あります。
また、指定によってはprivateなメンバまで見えます。

キーワード「リフレクション」でググってみてください。

投稿日時 - 2010-12-17 12:31:30

ANo.4

ああそうか, #2 を読んで気づいたんだけど「この設定した情報をBのインスタンスに一気に設定する」が実はあいまいなのか.
つまり
・それ以降に作る B のインスタンスに設定する (それ以前に作ったものは無視)
・とにかくすべての B のインスタンスに設定する
のかが区別しきれない.

#1 は表現をぼかしたので結果的にどちらにも対応しちゃってるけど, 前者を期待するなら (B または C にコンストラクタを書いたうえで) A をファクトリとする (だからもちろん継承関係は存在しない) のが正しいのかもしれない.

投稿日時 - 2010-12-17 12:23:06

ANo.3

オブジェクトを本当にコピーする必要があるのであればcloneの実装であろうと思います。

Cloneable、Object.clone()メソッドを参照してください。


※邪道な方法としてはRMIを使えばコピーが渡るはずです。

投稿日時 - 2010-12-17 07:20:35

ANo.2

質問そのものについての回答としては、
Bクラスにコンストラクタを定義することで解決すると思いますよ。

class B extends C{
 public B( int x, String str) {
  this.x = x;
  this.str = str;
 }
}

A a = new A();
a.setStr("aaa");
a.setInt(5);
B b = new B( a.getInt(), a.getStr() ); // getInt() や getStr() はprivate でない前提

ただ、他の回答者の方も指摘しているとおり、
あなたが何故「継承」を使っているのかが全然分かりません。
おそらく、「クラス」「インスタンス」「継承」など、
オブジェクト指向の理解が不十分なのだと思うのですよ。
あなたの質問内容を普通に書けば、下のようなプログラムになるはずで
継承を使う必要性が全くないのです。

class C {
 int x = 0;
 String str = "";

 public C() { }

 public C( int x, String str) {
  this.x = x;
  this.str = str;
 }

 void setInt(int x){this.x=x;}
 void setStr(String str){this.str=str;}
 int getInt(){return this.x;}
 String getStr(){return this.str;}

}

class Program {
 public static void main(String[] args) {
  C a = new C();
  a.setStr("aaa");
  a.setInt(5);
  C b = new C( a.getInt(), a.getStr() );
 }
}

「やさしいJava」などの入門書を1度読んでみることをお勧めします。

参考URL:http://www.amazon.co.jp/dp/4797355727

投稿日時 - 2010-12-17 02:45:09

ANo.1

A や B のメソッドに仕込んでおけばできると思うけど, 何を目的としてそういうことをしたいのかが想像できない....
特に「A で設定しているにもかかわらず, A のインスタンスにではなく B のインスタンスに影響する」ってのが謎な感じ. A のインスタンスに反映されるならわからんでもないんだけど.

投稿日時 - 2010-12-17 01:07:45

あなたにオススメの質問