K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[1899] Re:オーバーライド時の共変、反変について
投稿者:(ぱ)こと管理人
2015/02/24 02:39:59

はじめまして。最近この掲示板もすっかり閑散としてしまっていて、 投稿に気付くのが遅れてしまいました。すみません。 ご質問いただきありがとうございます。 引用の順番を変更しますが、結論から言えば、 >戻りの値の型が共変、引数の型が共変、 >ともにダウンキャストとなる、という認識ですが、 >なぜ、問題の有無の判断が変わってくるのでしょうか。 引数の型が共変なのはダウンキャストですが、 戻り値の型が共変なのはアップキャストだからです。 >”プログラミング言語を作る”内の8-3-5章にて >下の解説を読みました。 p.289のコードですね。 >class ShapeArray{ > Shape get(int index); > void set(int index, Shape shape); >}; > >class CircleArray extends ShapeArray{ > Circle get(int index); ・・・① > void set(int index, Circle circle); ・・・② >}; まず、このコードは、 p.249の補足で、JavaのArrayStoreExceptionの説明をしていますが、 JavaがArrayStoreExceptionを発生させるという実行時チェックを しなければならなくなった、ということについて、共変の考え方からも 説明できる、ということを示すためのコードです。 ここまではよいでしょうか。 p.249の補足のサンプルコードで、 1: Line[] lines = new Line[10]; 2: Shape[] shapes = lines; 3: shapes[3] = new Circle(); というコードがあったとき、Javaでは3行目でArrayStoreExceptionが 発生します。shapesはあくまでLineの配列であり、Circleの配列では ないからです。 これはJavaにおける配列の話ですが、Javaの配列をShapeArrayとか CircleArrayといったクラスで表現すると、p.289のコードのようになります。 ここで、CircleArrayのインスタンスcircleArrayがあったとして、 Shape shape = circleArray.get(i); というコードは、アップキャストなので合法ですが、 circleArray.set(i, shape); というコードは、ダウンキャストになります。CircleArray.set()の第2引数の 型はCircleなので、もしShapeを渡したければダウンキャストが必要になります。 Javaでは、このダウンキャストに相当する実行時例外が、ArrayStoreExceptionに なっている、と言えるでしょう。 この例ではCircleArrayがShapeArrayを継承しているので、もし引数の共変を 許せば、 ShapeArray shapes = circleArray; shapes.set(i, shape); と書けてしまいます。このshapes.set(i, shape);が、 まさにp.249のコードの shapes[i] = new Circle(); に相当するわけです。 これで回答になっているでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]