Javaのオブジェクト指向の要、カプセル化と継承をGitHub CopilotのAgentモードも使って理解するAIアシスト時代のJavaプログラミング入門(6)

対話型AI(人工知能)にアドバイスを受けながら進めるJavaプログラミングの入門連載。今回は、オブジェクト指向の要といえるカプセル化と継承を学習します。クラス構造の隠蔽と公開、クラスを再利用する方法について理解しましょう。

» 2025年09月11日 05時00分 公開

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「AIアシスト時代のJavaプログラミング入門」のインデックス

連載:AIアシスト時代のJavaプログラミング入門

本連載のサンプルコードをGitHubで公開しています。こちらからダウンロードしてみてください。


オブジェクト指向に求められる機能とは

 対話型AI(人工知能)にアドバイスを受けながら進めるJavaプログラミングの入門連載「AIアシスト時代のJavaプログラミング入門」前回は、Javaにおけるオブジェクト指向の機能として、クラスとインスタンス化、メソッドやコンストラクタについて学びました。「現実社会のモノや概念をプログラムで表現する」のがオブジェクト指向であることも学びました。

 しかしながら、オブジェクト指向とは果たしてこのような単純なものであるのか? という疑問も湧きます。現時点において多くのプログラミング言語で採用され、広く使われているのがオブジェクト指向です。クラスやメソッドといった基本的な機能に加えて、「現実社会を表現する」にふさわしい機能がまだまだあるに違いありません。

 今回は、ここからJavaのオブジェクト指向をさらに掘り下げていきます。そのための下地として、Visual Studio Code(以降、VS Code)からGitHub Copilot(以降、Copilot)に「オブジェクト指向についてメソッドやコンストラクタ以外の主な機能を重要度順に教えて。サンプルコードは不要です。」と投げてみました。そこで得られた回答が図1です。

図1 「オブジェクト指向についてメソッドやコンストラクタ以外の主な機能を重要度順に教えて。」の回答 図1 「オブジェクト指向についてメソッドやコンストラクタ以外の主な機能を重要度順に教えて。」の回答

【補足】サンプルコード不要

 前回までの回答を見ると、親切にサンプルコードも提示してくれることが多かったのですが、まずはどのような機能があるか知りたいので、サンプルコードは不要と付け加えました。何度か同じように質問することで、いずれ学習して、最初はサンプルコードを交えずに回答してくれるようになります。

 全部で10個、たくさんの項目を得られました。「重要度順に」と付けたので、ランキング順に並べてくれました。字面的にも難しそう、聞いたこともないような片仮名語が並んでいて、先に進むのがためらわれそうですね。ここはまず、オブジェクト指向にはこのような機能があるんだ程度に押さえておけば大丈夫です。「まとめ」にも、以下のように締めくくられていますね。

  • 最も重要なのは「カプセル化」で、データの保護と管理が基本です。
  • 次に「継承」と「ポリモーフィズム」が、コードの再利用性や柔軟性を高めます。
  • 他の機能は、設計や用途に応じて適切に使い分けることが重要です。

 最も重要とされるものから、順を追って深掘りしていきましょう。今回は、「カプセル化」と「継承」です。

カプセル化(Encapsulation)

 まずは「カプセル化」です。図1上の回答を見ると、「まとめ」に「データの保護と管理」とある他に、以下のように説明されています。

  1. データ(フィールド)とそれを操作するメソッドを1つのクラスにまとめ、外部から直接アクセスできないようにする仕組み
  2. メリット:データの保護、コードの可読性向上、変更の影響を最小限に抑える

 1.については、前回で学習した内容ですね。「データ(フィールド)とそれを操作するメソッドを1つのクラスにまとめる」というのは、オブジェクト指向の基本であるクラスの役割として説明した通りです。クラスは、カプセル化の機能も持っているわけです。すると、続く「外部から直接アクセスできないようにする」の部分が気になります。前回のサンプルでは、Catクラスにmeowメソッドを実装して呼び出していましたが、外部からアクセスできないとこのような使い方はできません。

 2.に示されているメリットも、1.の問題がクリアにならないと具体的にイメージしにくいようです。ですので、カプセル化について掘り下げる質問を改めて投げてみることにしましょう。「カプセル化についてもう少し詳しく。サンプルコードは不要です。」と投げてみました。そこで得られた回答が図2です。

図2 「カプセル化についてもう少し詳しく。」の回答 図2 「カプセル化についてもう少し詳しく。」の回答

カプセル化の目的

 図2から、カプセル化の目的を抜き出してみると以下のようにまとめられます。

  • データの保護:クラス内部のデータ(フィールド)を外部から直接変更できないようにすることで、不正な操作や予期しない変更を防ぐ
  • データの一貫性を保つ:データの変更は専用のメソッド(セッターやゲッター)を通じて行い、データの整合性を保つ
  • 実装の隠蔽(いんぺい):クラス内部の実装を隠し、外部には必要最低限のインタフェース(メソッド)だけを公開する。これにより、内部の変更が外部に影響を与えにくくなる
  • コードの可読性と保守性の向上:データへのアクセス方法を統一することで、コードの可読性が向上し、変更や拡張が容易になる

 一つ一つ理解するのは大変なのですが、要は「データの存在は外部から隠して、「窓口」としてのメソッドを公開する」ということのようです。そして、そのメソッドはゲッター、セッターと呼ばれるようです。まずは、フィールドは隠し、メソッドは公開すると単純に理解しておけばよさそうです。

カプセル化の方法

 では、どのようにフィールドを隠し、メソッドを公開するのでしょうか。これも回答が示されています。

  1. フィールドをprivateにする:クラス内部でのみアクセス可能にする
  2. 必要なメソッドをpublicで公開する:外部からデータを取得するための「ゲッター(getter)」や、データを変更するための「セッター(setter)」を提供する
  3. アクセス修飾子を適切に使う:private、protected、publicを使い分けて、アクセス範囲を制御する

 privateとかpublicとか聞いたことがないキーワードが出現していますね。では、これらの意味を探るために、具体的な例を実際のコードとして生成してもらいましょう。カプセル化のサンプル用に、プロジェクトencapsulateを作成してください。プロジェクトの作り方を忘れてしまった人は、第1回を参照してください。

 今回は、CopilotのAgentモードを使って、クラスファイルも自動生成してみます。VS Codeのチャットビュー下にある「Ask」をクリックして、プルダウンから「Agent」を選択するか[Command]+[Shift]+[I](macOS)/[Ctrl]+[Shift]+[I](Windows)キーを押してください(チャット履歴は消去されます)。そして、「encapsulateプロジェクトにCatクラスファイルをカプセル化を考慮して作成して。」と投げてみます。チャットビューには、作成あるいは変更されるファイルが示され、エディタビューには実際のコードが現れます(図3)。

図3 Agentモードで「encapsulateプロジェクトにCatクラスファイルをカプセル化を考慮して作成して。」の結果 図3 Agentモードで「encapsulateプロジェクトにCatクラスファイルをカプセル化を考慮して作成して。」の結果

 このように、Agentモードを使うと簡単な指示でファイルを作ってもらったり、プロジェクトも作成してもらうことが可能です。もちろん、Askモードのような使い方もできるので、いろいろ試してみるとよいでしょう。

【補足】Agentモード

 Agentモードは、従来のAskモード、Editモードに対して新しく追加されたモードで、その名の通り「代理人」のようにさまざまな処理を自動で実行してくれる機能です。特徴は、ここでも示したようにかなりざっくりとした質問(指示)でも受け入れてくれる点です。作成済みのファイルについても要望を伝えれば修正を施してくれるので、AIと対話しながらの作業といったことが可能です。

カプセル化のコード

 作成されたCatクラス(Cat.javaファイル)は自動で開かれているので、早速中身を見てみます。気になるprivateはというと、フィールドnameとフィールドageに付けられています(図4)。

図4 privateの付いたフィールドnameとフィールドage 図4 privateの付いたフィールドnameとフィールドage

 privateの役割は、既に書かれているように「そのフィールドをクラス内部からしかアクセスできないようにする」ことです。つまり、nameやageは、外部から見たり変更することができなくなります。これによって存在を隠し、不用意に変更されたりすることを防ぐわけです。カプセル化の名の通り、カプセルで包んで見えなくするのですね。

 privateによって見えなくなってしまったフィールドは、どのように読み取って変更すればよいのかというと、これも説明に登場していたゲッターやセッターと呼ばれるメソッドを使います。ゲッターやセッターのコードも作成されていて、getNameやgetAgeがゲッター、setNameやsetAgeがセッターです。ゲッターを通じてフィールドの値を取り出し、セッターによってフィールドに値を設定するのです。これらのメソッドにはpublicが付けられており、クラス外部から利用できるようにします(図5)。

図5 publicの付いたゲッターとセッター 図5 publicの付いたゲッターとセッター

 このように、大ざっぱに、隠したいものにはprivateを、見せたいものにはpublicを指定します。これが、「アクセス修飾子を適切に使う」で示されている内容です。privateやpublicはアクセスをコントロールする役割なので、アクセス修飾子というわけです(図6)。

図6 カプセル化 図6 カプセル化

 さて、ここでのゲッターやセッターは、それぞれフィールドの値を取得、あるいは設定するだけなので、これならフィールドをpublicにしても同じではないか? という疑問も湧くでしょう。そこで、図2の最後「例で考えるポイント」です。ここには、フィールドを直接公開する場合の問題点が示されていますが、セッターを適切に実装することで意図しない値の設定などからガードできるということも示されています。以下は、ゲッターとセッターでできることの一例です。

  • セッターで値を設定する際に、負の値を防ぐチェックを追加できる
  • ゲッターでデータを取得する際に、フォーマットを整えることができる

 具体的なコードはインラインチャットで追加できると思いますが、負の年齢というのはあり得ないので、そのような場合には無視したり、エラーとしたりすることができるでしょう。また、ゲッターでは年齢から生年に変換して返すということもできます。

こんな質問をしてみたい!

 ゲッターとセッターは基本的には単なるメソッドなので、どのような名前でも大丈夫そうですが、ここでの例を見る限り何かルールがありそうです。Copilotは特に言及していませんでしたが、ゲッターとセッターの命名規則について聞いてみると、なぜそのようにするのかがはっきりするかもしれませんよ!

継承(Inheritance)

 次は、2番目に重要とされている「継承」です。冒頭の図1上では、以下のように説明されています。

  1. 既存のクラス(親クラス)を基に新しいクラス(子クラス)を作成し、親クラスの機能を引き継ぐ仕組み
  2. メリット:コードの再利用性の向上、共通処理の統一

 継承の名の通り、親クラスとされるクラスの機能つまりフィールドやメソッドは、子クラスに引き継ぐことができるということです。これがいったいどのようなことで、どのような意義があるのか、継承について掘り下げる質問を改めて投げてみることにしましょう。「継承についてもう少し詳しく。サンプルコードは不要です。」と投げてみました。そこで得られた回答が図7です。

図7 「継承についてもう少し詳しく。」の回答 図7 「継承についてもう少し詳しく。」の回答

 またまた、たくさんの項目が回答されました。しかしながら、カプセル化と違って、継承というのは動作を説明されてもいまひとつイメージしにくいのではないでしょうか? そこで、質問を変えてみます。「継承の具体的なイメージをコードなしで。」と投げてみました。オブジェクト指向というのは現実社会のメタファですから、実在の何かで例えてくれることを期待します。そこで得られた回答が図8です。

図8 「継承の具体的なイメージをコードなしで。」の回答 図8 「継承の具体的なイメージをコードなしで。」の回答

 継承を、「動物」で例えてくれました。かなりシンプルな説明で、これでも十分理解できると思いますが、さらに簡略化すると、こんな感じでしょうか。

  • あらゆる動物に共通の機能をクラスとして作る
  • 動物の性質を備えるが機能が一部異なる動物を子クラスとして作る

 生物の系統樹のように、根っこの部分の生物をあらゆるクラスの親クラスとすれば、そこから派生していく生物を子クラスとしていく、そんなイメージになります。子クラスは、親クラスの性質を受け継ぎ、新たな性質を備えたり、親の性質を置き換えたりすることができます(図9)。なお、図8にある通り、親クラスは「スーパークラス」ともいい、子クラスは「サブクラス」ということもあります。

図9 継承 図9 継承

継承の目的

 動物に例えることで、継承が大まかにイメージできたことと思います。では、そもそもなぜそのような機能が用意されているかということを掘り下げましょう。図1上の回答においても、図7の回答においても、ほぼ同様のことが書かれています。それが、「コードの再利用」です。どうやら、継承においてはこの「コードの再利用」が重要そうです。そこで、「継承におけるコードの再利用について。」と投げてみました。そこで得られた回答が図10です。

図10 「継承におけるコードの再利用について。」の回答 図10 「継承におけるコードの再利用について。」の回答

 この回答を基に、簡単にまとめてみましょう。

1. 共通機能の集約

 複数のクラスで共通する機能があるとき、それを親クラスで実装すれば、それぞれの子クラスで個別に実装する必要がなくなるということですね。これは明らかに便利で効率がよさそうです。

2. 一元管理

 仮に、それぞれのクラスで同じ機能を実装していったとしたら、あるクラスの変更を他のクラスにも同じように反映する必要が出てきます。漏れや間違いが発生すると、クラスによって動作が異なるということになってしまいます。これでは具合が悪いですね。同じような機能は親クラスにまとめて、子クラスではそれを使うだけというようにすれば、仮に機能に変更があっても親クラスだけを修正すれば済みます。

3. コードの簡素化

 親クラスにある機能をそのまま使うのであれば、子クラスには改めて機能を実装する必要がないので、子クラスのコードが簡素になりますね。親クラスの機能をそのまま使わないにしても、使える部分だけでも使えばそれでも十分に簡素化できそうです。コードを書く量を減らせれば、それだけバグの発生する可能性も減らせるので安全といえそうです。

4. 一貫性の確保

 複数のクラスでデータの保存をそれぞれ実装したら、微妙に違った形式になってしまって具合の悪いことになりがちです。親クラスで統一した方法を用意しておけば、どの子クラスから保存しても同じ形式にできますね。

 コードの再利用には、開発効率と保守性を向上させたり、バグの発生を防いだりといったメリットがあることが分かります。

継承の方法

 では、どのように継承を実現するのでしょうか。ここまでの回答にはこれが一切なかったので、ここで聞いてみましょう。「継承の具体的な方法を教えて。」と投げてみました。そこで得られた回答が図11です(「コードなしで」と断る必要がなくなっていました)。

図11 「継承の具体的な方法を教えて。」の回答 図11 「継承の具体的な方法を教えて。」の回答

 項目がたくさんあるのですが、まずは1.と2.に着目しましょう。それぞれ、親クラスと子クラスの定義方法について書かれています。

1. 親クラス(スーパークラス)の定義

 説明を読むと、共通のプロパティとメソッドを定義するという他は、これまで出てきたクラス定義と変わらなさそうです。

【補足】プロパティ

 プロパティという初出の用語が登場していますが、ここではフィールドと同じようなものと思って構いません。値の読み出しや設定が可能なもの全般をプロパティと呼ぶ、と理解しておきましょう。

2. 子クラス(サブクラス)の定義

 子クラスは、extendsキーワードを使って定義するとあります。親クラスから引き継ぐメンバーについての記述もありますが、それは後で改めましょう。早速、extendsキーワードを使ったクラス定義の構文を知りたいところです。少し飛びますが、図11の下部にある「例(コードなしの説明)」の箇所をコードありで示してもらうことにしましょう。

【補足】メンバー

 ここにもメンバーという初出の用語が登場していますが、これはフィールドやメソッドを全てまとめたものと思って構いません。クラスにはさまざまなメンバーがいる、というイメージです。これに倣って、フィールドをメンバー変数と呼ぶこともあります。

継承のコード

 「例のコードを具体的にお願い。」と投げてみました。Animalクラス、Dogクラス、Catクラスと、mainメソッドのコードが示されるので、それらをinheritanceプロジェクトを作ってソースファイルとして保存しましょう。全てApp.javaファイルに入れてしまって構いません。mainメソッドのクラスだけ、MainからAppに変更しておきます。

 まずは継承元となるAnimalクラスです(図12)。

図12 Animalクラスのコード 図12 Animalクラスのコード

 Animalクラスのコードは、前回で学んだ内容で十分理解できるものですが、1カ所だけ親クラスならではの記述があります。それがprotectedキーワードです。図2において、アクセス修飾子としてprivate、public、protectedが挙げられていましたが、そこではprotectedを使いませんでした。このprotectedは、外部には見せたくないが、子クラスにだけは見ることを許す、という意味です。privateだと自クラスの中でしか見えないので、継承した子クラスが使えないからです。もちろん、子クラスにも見せたくないものをprivateにするのは変わりません。

 では、継承先はどうなるのか、Dogクラスを見てみます(図13)。Catクラスも似たようなものなので、各自でのぞいてみてください。なお、DogクラスではAnimalクラスのメソッドを置き換える「オーバーライド」という処理が入っています。

図13 Dogクラスのコード 図13 Dogクラスのコード

 注目すべきは、クラス定義に使われているextendsキーワードです。これを、「class XXX」に続けることで、継承でクラス定義することを表します。extendsの名の通り、「拡張する」というわけですね。

 その他は、通常のコンストラクタ、メソッド定義と変わりませんが、幾つか見慣れないコードがありますね。一つは、コンストラクタの中にある「super(name);」と、もう一つはmoveメソッドの前にある「@Override」です。

  • 親クラスのコンストラクタを呼び出すsuper

 superは、親クラスのコンストラクタを呼び出すときに使います。Dogクラスのコンストラクタを見ると、superを呼び出しているだけです。これなら親クラスのコンストラクタが継承されるからわざわざDogクラスにはコンストラクタはいらないのでは? と思われるでしょう。Copilotは特に触れていませんでしたが、Javaでは「コンストラクタは継承されない」という性質があるのです。このため、子クラス側でもコンストラクタを定義し、必要なら親クラスのコンストラクタに処理を委ねるのです。この特別なメソッド呼び出しがsuperです。

  • オーバーライドを明示する@Override

 @Overrideは「アノテーション」と呼ばれるものの一つで、続くメソッド定義が親クラスのものを置き換えるものであることを示します。overrideとは上書きの意味で、親クラスのメソッドを上書きして隠してしまいます。メソッドがオーバーライドされると、親クラスのメソッドではなく子クラスのメソッドが呼ばれるようになります。オーバーライドによって、子クラスに合わせた動きとなるメソッドとすることができるようになるわけです。

 クラスをインスタンス化して、呼び出す側のコードも見てみましょう。その前に、プログラムを実行して結果を確認してみます(図14)。

図14 継承サンプルの実行結果 図14 継承サンプルの実行結果

 これを踏まえて、呼び出し側のコードすなわちmainメソッドを見てみます(図15)。

図15 mainメソッドのコード 図15 mainメソッドのコード

 注目すべき点は幾つかあります。まず、子クラスであるDogとCatのインスタンスから親クラスであるAnimalのmoveメソッドを呼び出していますが、Dogクラスではオーバーライドしたために挙動が変わっている点です。Catクラスでは基のmoveメソッドの挙動となっているので、これからオーバーライドの働きが理解できますね。

 最後に、「多態性の例」とありますが、これは図1上などでも登場していた「ポリモーフィズム」を指します。これも、オブジェクト指向では非常に重要な概念です。コードの意味については次回にインタフェースとともに取り上げます。

 カプセル化も、継承も機能は豊富です。今回、説明しきれなかった機能がたくさんあるので、Copilotの回答を読んでみて、さらに質問するなどして学習を深めていってください。

こんな質問をしてみたい!

 継承の説明を読むと、設計が大事とくどく書かれています。何が何でも継承関係にすればよいというわけではないというのは分かりますが、アンチパターンというものを聞いてみると、どのようなケースで継承を使うべきかがより深くイメージできるかもしれませんよ!

まとめ

 今回は、オブジェクト指向の要であるカプセル化と継承についてAIに聞きながら学習しました。

 次回も、同じく要であるインタフェースとポリモーフィズムについて学習していきます。

筆者紹介

WINGSプロジェクト 山内直

WINGSプロジェクト所属のテクニカルライター。出版社秀和システムを経てフリーランスとして独立。ライター、編集者、開発者、講師業に従事。屋号は「たまデジ。」。

たまデジ。 | たまプラーザで生活、仕事する。(https://naosan.jp/

WINGSプロジェクト

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティー(代表山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手掛ける。2021年10月時点での登録メンバーは55人で、現在も執筆メンバーを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。

サーバーサイド技術の学び舎 - WINGS(https://wings.msn.to/
RSS(https://wings.msn.to/contents/rss.php
X: @WingsPro_info(https://x.com/WingsPro_info
Facebook(https://www.facebook.com/WINGSProject


Copyright © ITmedia, Inc. All Rights Reserved.

アイティメディアからのお知らせ

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。