});前回「クラスを簡単に理解する」まで、プリミティブ型とクラス型について説明してきました。コンピュータの中には結局のところCPUとメモリしかありません。「変数は箱だ」といった例え話よりも、変数がどのようにメモリを使うのかで考えた方が意外に分かりやすいものです。今回はクラスの特徴的機能である「継承」について説明します。継承はJavaをはじめとするオブジェクト指向言語の代表的概念ですが、初学者には最初の壁となって立ちはだかります。クラスについておさらいしましょう。クラスには、メンバ変数としてプリミティブ型やほかのクラス型変数を要素として格納できる。クラスのインスタンスを生成すると、メンバ変数を格納するのに必要なサイズのメモリ領域が確保される。前回は地図上の地点を表現するクラスとして、次のようなクラスを作りました。longitude;}GeographicInfo型のクラスには、経度と緯度を表現するためにdouble型のlatitude(緯度)とlongitude(経度)というメンバ変数が定義されています。GeographicInfo型のクラスを使うことで、ある場所の経度と緯度を別個の変数として管理しなくてもよくなります。プログラムに修正はつきものです。経度と緯度のほかに高度も扱いたくなったとしたら、どうしたらよいでしょうか。簡単な解決策は、別のクラスを新しく定義することです。height;}この方法のデメリットは、GeographicInfo型を使って作った既存のプログラムと互換性がなくなることです。GeographicInfo型とGeographicInfo3D型はまったく関係のない別のクラスですので、元のコードとの互換性を保つには、ソースコードをすべて変更して、GeographicInfo3D型に置き換えなくてはいけません。別のデメリットもあります。height;」の1行だけです。これでは、クラス定義の3分の2が重複していることになります。複雑なクラスであれば、メンバ変数を1つ追加するためによく似たクラスを定義することの無駄はもっと多くなります。クラスの継承とは定義の流用であるそこでJavaのクラスには、「継承」という機能が用意されています。実際のソースコードを見てみましょう。<元になるクラス名>」という文と追加するメンバ変数を実際に定義するだけです。それでは実際に2つのクラスを使ったプログラムを作ってみましょう。10.0;System.out.println(g.latitude);System.out.println(g.longitude);System.out.println(g.height);}}ちょっと長めのプログラムですが、やっていることは3つしかありません。最初のブロックでは、GeographicInfo型のクラスを定義しています。次のブロックでは、GeographicInfo型を継承してGeographicInfo3D型を定義しています。最後のブロックはプログラム本体で、GeographicInfo3D型のインスタンスを変数gに代入し、メンバ変数latitude、longitude、heightに値を代入して画面に表示しています。それでは、念のためこのプログラムを実行してみましょう。UsingGeographicInfo3D35.66139.7510.0C:\DOCUME~1\MYDOCU~1\MYJAVA~1>GeographicInfo3Dでは、メンバ変数としてheightだけを宣言しており、latitude、longitudeという変数を定義していません。その代わりに、GeographicInfo3D型がGeographicInfo型を継承している、と定義しています。そのため、GeographicInfo3D型の変数gを使って、GeographicInfo3D型で直接定義されていないlatitude、longitudeの値を表示できるわけです。Javaでは、GeographicInfo型のように元になるクラスのことを「スーパークラス」、GeographicInfo3D型のように元になるクラスの定義を流用する側のクラスを「サブクラス」と呼びます。正式なJava用語ではありませんが、スーパークラスのことを「親クラス」や「基底クラス」あるいは「継承元クラス」、サブクラスのことを「子クラス」や「派生クラス」という場合もあります。クラスを継承すると、スーパークラスで定義したメンバ変数などをサブクラスで流用できるというメリットがあります。同じようなクラスを定義しなくてはならないが、微妙に異なるという場合は、まずすべてのクラスに共通する要素をスーパークラスで定義し、異なる部分だけを個別のクラスとして定義することで、プログラムを効率的に開発しましょう、というのがオブジェクト指向の基本的な考え方の1つとされています。クラスを継承すると何が起きるのかクラスの継承は元のクラスを流用することです。ところが「Java入門」といった書籍や記事を読むと、次のような「例え話」が出てきます。ありがちなクラス継承の説明図クラスの継承とは、「電気製品」クラスを継承して「テレビ」クラスを作り、「テレビ」クラスを継承して「カラーテレビ」クラスを作るといったように、サブクラスがスーパークラスの性質を受け継ぐことである特にどの本というわけではないのですが、どうしてこういう例え話が出てきてしまうのか、私にはさっぱり分かりません。クラスの概念を哲学用語か何かのように説明するのはいいかげんやめにしてほしいものです。だいたい、テレビ型やカラーテレビ型クラスを作るJavaプログラマがどれだけいるというのでしょう。第2回「Javaの変数の本質を知る」で指摘した「変数は箱だ」説同様、この手の例え話を信じると、プログラムがどのようにメモリを使うのかという視点が抜け落ちてしまいます。そこで、クラスの継承がどのようにメモリを使うのか見てみましょう。スーパークラスとなるGeographicInfo型のインスタンスは次のようにメモリを使います。GeographicInfo型のインスタンスが使うメモリ領域GeographicInfo型にはdouble型のメンバ変数latitudeとlongitudeが含まれますので、全部で16bytesのメモリを消費します。型にdouble型のメンバ変数heightを追加定義したものです。GeographicInfo3D型のインスタンスは次のようにメモリを使います。従ってGeographicInfo3D型のインスタンスは、スーパークラスであるGeographicInfo型の16bytesにメンバ変数heightの分8bytesを加えて合計24bytesのメモリを消費します。例え話を使った継承の説明では、こういう視点にたどり着くまでにずいぶん時間がかかります。そもそも、継承を示すキーワードである「extends」は「延長する」という意味です。クラスの継承とは「使用メモリ量の付け足しだ」と思えば理解はずいぶん早まるはずです。クラス継承の理解を深めるクラスを継承させるメリットは、クラス間の関係をプログラムの中に埋め込めることです。初めに説明したように、GeographicInfo型とGeographicInfo3D型をまったく独立して定義することもできますが、GeographicInfo型からGeographicInfo3D型を継承させることで、2つのクラス間の関係まで定義できるのです。このことを確かめるために、次のプログラムを実行してみてください。h;System.out.println(g.latitude);System.out.println(g.longitude);}}このコードを実行すると以下のような結果になります。SubAsSuper35.66139.75C:\DOCUME~1\MYDOCU~1\MYJAVA~1>初めに紹介したプログラムとよく似ていますが、決定的に異なるのは、スーパークラスであるGeographicInfo型の変数gを使ってGeographicInfo3D型として生成したインスタンスのメンバ変数latitudeとlongitudeの値を表示していることです。GeographicInfo3D()」という文で生成されたGeographicInfo3D型のインスタンスの先頭アドレスが格納されます。gはGeographicInfo型ですので、GeographicInfo3D型固有のメンバ変数であるheightにはアクセスできません。先頭から16bytesまでにあるlatitudeとlongitudeにはアクセスできるわけです。このことをクラス継承の例え話で理解するのはかなり厄介です。「カラーテレビ型はテレビ型の性質を受け継いでいるから、カラーテレビ型のインスタンスはテレビ型のインスタンスとしても扱える」といわれても、テレビの説明をしたいのかプログラミング言語の話をしたいのかさっぱり分かりません。クラスの継承の基本は「使用メモリ領域の付け足し」ですので、サブクラスのインスタンス化によって確保されたメモリ領域をスーパークラスのインスタンスとして扱えるのは当たり前と考えるべきなのです。今回まで「変数はメモリをどのように使うのか」という視点でJavaを解説してきました。クラスについて説明をし尽くしていませんが、これ以上はメモリ領域の面だけでは解説できません。そこで次回からは制御文や関数の説明に入ります。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。