継承は,カプセル化と並んでオブジェクト指向の重要な要素です。あるクラスを元にして,機能を拡張したクラスを新たに作り出す機能です。元になるクラスを「スーパークラス」あるいは「親クラス」と呼びます。Javaでは「extends」キーワードで継承を実装します。

 Part5のテーマは「継承」です。これは,既存のクラスに属性や機能を追加して新しいクラスを作る機能を指します。オブジェクト指向の中でも重要な考え方です。

 継承の話をする前に,構造化プログラミングにおけるプログラムの再利用について簡単に説明しましょう。構造化プログラミングでは「モジュール化」という手法でプログラムを再利用します。モジュールは,関数などの処理を再利用しやすいようにまとめたもので,例えばファイル入出力モジュールのように,プログラムでよく利用する機能をまとめて開発の効率化を図ります。

 ところが実際の開発現場では,せっかくモジュールを作っても無駄になることがよくあります。一般に,ソフトウエアは常に新しい機能を取り入れて変化していくものです。既存のモジュールをそのまま使うだけでは,機能追加の要求にこたえ切れません。そこで,既存のモジュールのコードをコピーして新しい関数を追加し,新規にモジュールを作ることがよくあります。しかし,このような作業を繰り返していると,少しずつ機能の違うモジュールがたくさんできてしまいます。それぞれのモジュールが正しく動作しているうちは問題ありませんが,コピー元のコードにバグが見つかったときは大変です。そのコードを利用したすべてのモジュールを再点検しなければなりません。

 オブジェクト指向プログラミングでは,継承を利用してこのような問題を解決します。継承を利用すると,過去のプログラムの再利用が容易になるだけでなく,機能の拡張や,拡張後のコードの管理も簡単になります。また,継承はオブジェクト指向の重要な要素である「ポリモーフィズム」の基礎となりますので,しっかりと理解しておきましょう。

既存のクラスをベースに新しいクラスを作り出す

 継承とは,あるクラスを元にして,機能を拡張したクラスを新たに作り出す機能です。元になるクラスを「スーパークラス」あるいは「親クラス」と呼びます。

 もう少し詳しく言うと,継承とはスーパークラスにフィールドやメソッドを追加して新しいクラスを作ることを指します。この新しいクラスを「サブクラス」あるいは「子クラス」と呼びます。スーパークラスには,Javaが標準で備えるクラスライブラリを利用してもよいですし,自分が作ったクラスを利用することもできます。

 継承の基本的な書式を紹介しましょう。スーパークラス側に手を加える必要はありません。サブクラスの宣言文には「extends」というキーワードを追加し,スーパークラスにしたいクラスの名前を後に記述します。リスト1を見てください。

リスト1●継承の例
リスト1●継承の例
[画像のクリックで拡大表示]

 MyExtends1のクラス定義の1行目を見ると,extendsというキーワードの後にMyClass1と記述してありますね。つまり,MyExtends1はMyClass1のサブクラス,逆にMyClass1はMyExtends1のスーパークラスになります。

 MyExtends1の2行目でtemp2というメソッドを定義しています。このメソッドは,MyClass1クラスのtemp1メソッドを呼び出した後,printlnメソッドで文字列を表示しています。このようにサブクラスでは,スーパークラスのメソッドを,プログラム内でインスタンスを明示的に生成することなく利用できます。サブクラスのインスタンスを生成する時点で,Java仮想マシンが自動的にスーパークラスからインスタンスを生成してくれるからです。

 さらに,スーパークラスの変数やメソッドに対して,あたかもサブクラスの変数やメソッドであるかのようにアクセスできます。リスト2はMyExtends1クラスを利用するTest1クラスのコードです。

リスト2●リスト1で作成したクラスを呼び出すコード
リスト2●リスト1で作成したクラスを呼び出すコード
[画像のクリックで拡大表示]

 MyExtends1クラスのインスタンスを生成し,その参照値を使ってスーパークラスであるMyClass1のtemp1メソッドを呼び出した後,MyExtends1クラスのtemp2メソッドを呼び出しています。リスト2の実行結果は図1のようになります。

図1●Test1クラスの実行結果
図1●Test1クラスの実行結果

 1行目はMyClass1クラスのtemp1メソッドが表示している文字列です。2行目はMyExtends1のtemp2メソッドが呼び出しているMyClass1クラスのtemp1メソッドによる表示,3行目はMyExtends1のtemp2メソッドのprintlnメソッドによる表示です。

 このように継承を使うと,サブクラスからスーパークラスの機能を利用できるようになるだけでなく,サブクラス側にメソッドを記述することによってスーパークラスにない機能を簡単に追加できます。さらに,ソースコードのコピー&ペーストと異なり,元になる同じコードが散在しませんから,スーパークラスを修正すれば,すべてのサブクラスに反映されます。

 ただし,スーパークラス側で宣言している変数やメソッドが,すべてサブクラス側で利用できるわけではありません。例えば,スーパークラスでprivate宣言している変数やメソッドは,たとえサブクラスといえども呼び出すことはできません。