【Javaお勉強日記】型の自動変換についてまとめる
※実際に型が自動変換できるわけではない。厳密には「参照の自動型変換」だけど、Javaの場合はメモリ操作は裏で勝手にやってくれるので、プログラム書く側からすれば自動変換に見える。
型の自動変換はどのように行われているか
例えばこんな感じにBookクラスを継承したComicクラスがあるとして
Comicクラスの青い部分が、Bookクラスから継承した部分。
この、Comicクラスなら、Book型のインスタンスを作るのに必要な要素が揃っているので、そのままBook型の変数に無理矢理突っ込む事ができる。
Book book1 = new Comic(title, publisher, author, sireisTitle)
ってな具合。
その時に何が行われているかというと
・まず、Comicクラスのインスタンスが普通に作られる。
・その後、Bookクラスに存在するメンバだけにアクセス出来る参照がbook1に入る。
・book1に入っている(参照でアクセス出来る)Comicのインスタンスには、authorもsireisTitleも格納されてはいるが、getAuthor()しても使えない。
まず、Comicクラスのインスタンスがメモリの中に作られる。
Comicクラスのインスタンスを、Comic型の変数に入れた場合は、変数の中には、Comicクラスの全てのメンバ(への参照)が入る。
それを、Book型の変数へ代入した場合、
Book型にも存在するメンバ(への参照)だけが入り、残りのメンバについては「メモリ上には存在しているけど、アクセスはできない」という状態になる。
でも、とりあえず、これでBook型のオブジェクトとして使うことができる。
例えば、本棚管理アプリを作っていて、「雑誌」「漫画」「新書」...と色々な種類の本を取り扱っていたとして、「でもここではまとめて「本」としてtitleだけ取り扱いたいんだけど、一々型が違って面倒だなぁ」「全部Book型にしちゃえばらくちん!」と言うような時に使える。
スーパークラスからサブクラスへの暗黙の型変換はできない
だって要素が足りないから!
Comic型→Book型への変換のときは、要素が多い方→少ない方への変換だったので、余計な部分を切り捨てれば作れた。
(これを、アップキャスト(継承ツリーの下位から上位への変換なので「アップ」)と呼ぶ)
でも、Book型→Comic型へ変換しようとすると、要素が少ない方から多い方を作ることになるので、足りない部分が出てくる。そのため自動では型変換ができないようになっている。
(これは、継承ツリーの上位から下位への変換なので「ダウンキャスト」)
「暗黙の」が無理なら明示的にすれば良い
「変数の型はBook型だけど、実体はComic型なんだよね~」という変数からなら、Comic型へダウンキャストできる。だってメモリ上の実体には全部要素が揃ってるから。
ので、まず、「変数の型は違うけど、実は同じ型なんじゃない?」っていうのをチェックしてから、ダウンキャストするようにする。
そんなときに活躍するのが instanceof演算子。
if(book1 instanceof Comic){ // book1の実体がComicクラスのインスタンスならTrue
Comic comic1 = (Comic) book1;
// (Comic) book1と書くことで、強制的にComic型にキャストする
}
という感じで使う。
これは、仮に、Comicクラスをさらに継承して作られた、「初回特典付きコミック」サブクラスなんてのが作ってあったとして、その「特典付き」サブクラスと比較してもTrueになる。
なぜなら「特典付き」サブクラスはComicクラスに存在するメンバを全て継承して作られており、つまりBook型からComic型にダウンキャストするのに必要なメンバは全部揃っているから。
これは、例えば何でもかんでもObject型で返ってきちゃうメソッドの戻り値を、本来の型に直して使いたい時なんかにこうする。
(つまり、「明示的にやればダウンキャストできる」とはいっても、足りない部分に無理矢理初期値を突っ込んでBook型のインスタンスをComic型として扱う、みたいなことは出来ないので注意)
この記事が気に入ったらサポートをしてみませんか?