見出し画像

【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クラスのインスタンスがメモリの中に作られる。

画像2

Comicクラスのインスタンスを、Comic型の変数に入れた場合は、変数の中には、Comicクラスの全てのメンバ(への参照)が入る。

それを、Book型の変数へ代入した場合、

画像3

Book型にも存在するメンバ(への参照)だけが入り、残りのメンバについては「メモリ上には存在しているけど、アクセスはできない」という状態になる。
でも、とりあえず、これでBook型のオブジェクトとして使うことができる。

例えば、本棚管理アプリを作っていて、「雑誌」「漫画」「新書」...と色々な種類の本を取り扱っていたとして、「でもここではまとめて「本」としてtitleだけ取り扱いたいんだけど、一々型が違って面倒だなぁ」「全部Book型にしちゃえばらくちん!」と言うような時に使える。

スーパークラスからサブクラスへの暗黙の型変換はできない

画像4

だって要素が足りないから!

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型として扱う、みたいなことは出来ないので注意)

この記事が気に入ったらサポートをしてみませんか?