- - PR -
スーパークラスのキャストについて
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-04-08 11:33
またもや初歩的な質問ですいません。
ダウンキャストについてです。 実際よく考えてから使うべきなのは解ったのですが、ではどうしても使いたいとき、どう使えばいいのでしょうか? 使い方がよくわからなくて、ClassCastExceptionが発生します。 /** * 実行クラス */ class CastTest { public static void main(String[] args) { //スーパークラスのオブジェクトを作成 CastObject obj=new CastObject(); //サブクラスにダウンキャスト subObject1 s=(subObject1) obj;/*!![ClassCastException発生]!!*/ s.setEx("cast"); System.out.println(s.getEx()); } } /** * スーパークラス */ class CastObject { } /** * サブクラス1 */ class subObject1 extends CastObject{ private String ex; //Getterメソッド public String getEx(){ return ex; } //Setterメソッド public void setEx(String str){ ex=str; } } インスタンスの違いから発生していると思うのですが、どう直せばいいのか考えても思いつきません。実行クラスの CastObject obj=new CastObject(); ↓ CastObject obj=(CastObject) Class.forName("subObject1").newInstance(); とすると例外は発生しなくなるんですが、他に方法は無いのでしょうか? オブジェクト指向がしっかりと理解できていないと思うので、これがそのヒントになるような気がしています。ホントにわがままな質問ですが、どなたか教えてください。 宜しくお願いします。 | ||||||||||||||||
|
投稿日時: 2005-04-08 12:05
たとえば、こういう風に使います。
ダウンキャストする場合は、あくまで、目的のクラスかまたは、 そのスーパークラスでないといけないわけです。 たとえば、「会社」をスーパークラス、「ト○タ」「ス○キ」をサブクラスとします。 この場合、「ト○タ」「ス○キ」はいつでも「会社」として扱えます。 逆に「会社」だからといって、「ト○タ」「ス○キ」そのものとして扱える訳じゃありません。 この辺はオブジェクト指向の「継承」というやつです。 | ||||||||||||||||
|
投稿日時: 2005-04-08 12:33
例題のMainとは異なるのですが、、
1.サブクラスとしてインスタンスを生成してスーパークラス(またはインターフェイス)で扱っている。 2.なんらかの必要性があってサブクラスを識別する。 このような条件の場合、以下のような方法があります。
[ メッセージ編集済み 編集者: ロス 編集日時 2005-04-08 12:34 ] | ||||||||||||||||
|
投稿日時: 2005-04-08 13:45
こういうケースってどういう時に有効なのでしょうか。 ファクトリから取得すべきオブジェクトが増えた場合、取得元で コードの修正(instanceofの追加)が必須になりますよね。 キャストせずに親クラスのメソッド叩いて、実は中身の 実装が変更されてても叩き元は気にしない、という使用 方法なら理解できるのですが。。 | ||||||||||||||||
|
投稿日時: 2005-04-08 15:28
みなさんありがとうございます。
Edossonさん
なるほど。やっぱり、親クラスのオブジェクトを作成時に、子クラスのオブジェクトとして、作成して、「会社」=「ト○タ」としてから「会社」を扱うしかないのですね。 よくわかりました。 ロスさん instanceofで条件分岐する時の、子クラスのリストを取得する方法があれば使用可能ですね。あと、似ている感じのコードについて書かれているページを見つけたのですが、[←ここ]の部分がどういう状況なのかよくわかりません。質問は変わってしまいますが、よろしければ、教えて頂けないでしょうか?(ホントは[←ここ]以外もよく解らないんですが) http://www-6.ibm.com/jp/developerworks/java/010907/j_j-diag4.html#6
自分の中に自分を持つ???ホントに物わかりが悪くてすいません。 ぼちさん この間もお返事頂いてありがとうございました。
?????頭が悪くてすいません。どういう状況かわかりません。教えてください。 | ||||||||||||||||
|
投稿日時: 2005-04-08 15:48
私もぺーぺーなもんで、interfaceのテクニカルな使い方は
よくわかっていませんが、interface使って何がうれしいって 実装を使用者側が意識しなくていいことだと思いまして。
HogeFactoryはgetDAOで return new B()もしくはreturn new C()で返すと。 DBにMySQL対応が入った場合は、class Dでも作ればいいです。 でもMain側にコードの修正はいらないです。 こういう使い方が定石?なのかな、と。 [ メッセージ編集済み 編集者: (株)ぽち 編集日時 2005-04-08 15:50 ] | ||||||||||||||||
|
投稿日時: 2005-04-08 15:55
newで作成されているのは、あくまでも子クラスです。 「しかない」のではなく、これが当たり前なのですが、ま、ぼちぼちなれていきましょう。
「インスタンス」「生成」をキーワードに調べてみてください。
ふつうは、このような条件分岐は行いません。 こんな感じでしょうか。
[ メッセージ編集済み 編集者: Edosson 編集日時 2005-04-08 16:00 ] | ||||||||||||||||
|
投稿日時: 2005-04-08 17:41
> (株)ぽち さん
「どうしても」サブクラスにしか定義されていないメンバやメソッドにアクセスする場合ですね^^; 設計上、そういう状態を避けるのが一番よいと思います。 > fly_moon さん
後の例でも出てくるのですが、「キャストせずに利用」=「親クラスのインターフェイスだけを意識して、実装は実際のインスタンス(子クラス)に委譲する」ということだと思います。 お二方の例を見ると分かるように、ダウンキャストが必要になると思ったら、本当に必要なのかどうかを設計レベルで見直したほうがよいと思います。 ((株)ぽちさんは「インターフェイス」を使って実装クラスに動作を任せています) (Edossonさんは「アブストラクトクラス」を使って子クラスに動作を委譲しています) 最初の例で言うと、(親クラスがアブストラクトクラスだとして) /** * 実行クラス */ class CastTest { public static void main(String[] args) { //スーパークラスのオブジェクトを作成 // CastObject obj=new CastObject(); CastObject obj=new subObject1(); //サブクラスにダウンキャスト // subObject1 s=(subObject1) obj;/*!![ClassCastException発生]!!*/ // s.setEx("cast"); obj.setEx("cast"); // System.out.println(s.getEx()); System.out.println(obj.getEx()); } } /** * スーパークラス */ class abstruct CastObject { > //Getterメソッド > public abstruct String getEx(); > > //Setterメソッド > public abstruct void setEx(String str); } /** * サブクラス1 */ class subObject1 extends CastObject{ private String ex; //Getterメソッド(オーバーライド) public String getEx(){ return ex; } //Setterメソッド(オーバーライド) public void setEx(String str){ ex=str; } } としてみてはどうでしょうか? |