お久しぶりです!
バーチャル高専女子、七瀬真冬です。
今回はオブジェクト指向解説記事の第2弾!!
「オブジェクト指向」という概念を構成する重要な要素のひとつである「カプセル化」について解説するよ!!
ちなみにこの「カプセル化」という概念、結構奥が深いです。
私の技量では、1回分の記事だけではとても説明しきれません。なので、
・その2(今回分)…カプセル化の概要と「アクセス修飾子」について。
・その3…「getterメソッド」の使い方と存在意義について。
・その4…「setterメソッド」の使い方と存在意義について。
という3部構成でお送りします!!
なお、今回の記事は第1弾の内容を理解している人向けの内容になっています。
自信がない人は、以下のリンクからもう一度復習しておきましょう。
■ 本記事の対象読者
・オブジェクト指向解説記事の第1弾を読んだよ!
・Javaの開発環境を構築済みだよ!
・「クラス」「フィールド」「メソッド」「インスタンス」「コンストラクタ」という言葉について理解してるよ!
といった人向けの記事になります。
■ 注意!!
私の記事は「オブジェクト指向ってのはこういうもんだ!深く考えるな!!」的なスタンスになっています。
なので、割とざっくりした抽象的な説明が多いです。ご了承の程。
私の記事だけ読んでいると考えが偏ってしまうかもしれないので、他のサイトや書籍も参考にしながら「オブジェクト指向」の考え方を習得していくことをおすすめします。
あと、スマホ版のレイアウトでは若干ソースコードの表示が崩れます。
スマホで見てる人は、PC版での閲覧を推奨します!
Webブラウザの設定に『PC版サイトを表示』みたいなやつがあるはずなので、それを選択してね。
■ 筆者の開発環境
・OS:Windows 10
・IDE:Eclipse Java 2019-06
スポンサーリンク
■ 「カプセル化」の本質は「思いやり」!!
まず最初に、「カプセル化」について軽く説明しましょう。
詳しいことは後から教えるので、今はなんとなく雰囲気だけ理解してもらえればOKです。
「カプセル化」とは、オブジェクト指向プログラミングにおいて「効率よくプログラミングを行うための考え方」のひとつです。
「カプセル化」の本質は、ズバリ「他人への思いやり」です。
上手にカプセル化ができる人は、他人への思いやりがある優しい人だと言えます。
前回の記事で説明したとおり、Javaのようなオブジェクト指向言語では「クラス」単位でプログラミングを行いますよね。
チームで開発を行う場合、あなたが作った「クラス」を、他の人に使ってもらうような場面が多くあると思います。
例を挙げるとしたら… そうですね…。
・あなたは、とあるゲーム制作会社で新作RPGを作るプロジェクトのメンバーの一員で、「勇者」「敵モンスター」のクラスの開発を担当する。
・あなたが開発したこれらのクラスを、戦闘システムを開発している他メンバーに使ってもらう。
みたいな感じだったらイメージしやすいかな?
このとき、あなたが作った「勇者クラス」「敵モンスタークラス」に対して「カプセル化」が適切に行われていると、嬉しいことがたくさんあります。
具体的には、
・クラスを使う人が、「間違った使い方」をすることがなくなる!!
・クラスの間違った使い方によって、想定外のバグが発生することがなくなる!!
・バグが発生したときに、原因を突き止めやすくなる!!
・クラスを使う人に、「アイツが作ったクラスは使いやすくて良いなぁ」と思わせることができる!!
などなど。いいことずくめです。
「カプセル化」を適切に行ったクラスを書けるようになれば、結果として「安全で、バグが少なくて、メンテナンスしやすいシステム」を効率よく作ることができるようになります。
しっかりカプセル化の概念を理解して、思いやりに溢れたコードを書けるようになりましょう!!
スポンサーリンク
■ 「アクセス修飾子」を理解しよう。
カプセル化について詳しく説明する前に、ひとつだけ理解しておいてほしい概念があります。
それは「アクセス修飾子」と呼ばれるものです。
「バーチャル高専女子まふゆちゃん」をモデルにした、Mafuyuクラスを使って説明するね。
Mafuyu.javaを作成して、以下のMafuyuクラスを書いてみましょう。
フィールドが4つ定義されているだけの簡単なクラスです。
public class Mafuyu { int age = 17; String costume = "セーラー服"; String hairColor = "シルバー"; String pantyColor = "水色"; }
これら4つのフィールドに、「public」というキーワードをつけてみてください。
以下のようになります。
public class Mafuyu { public int age = 17; public String costume = "セーラー服"; public String hairColor = "シルバー"; public String pantyColor = "水色"; }
さて、ひとまずMafuyuクラスはこれでOKです。
今度はMain.javaを作成して、Mainクラスを書きましょう。
mainメソッド内でMafuyuクラスのインスタンス"mafuyu"を生成して、4つのフィールドの値を表示するコードを書いてください。
public class Main { public static void main(String[] args) { Mafuyu mafuyu = new Mafuyu(); System.out.println("まふゆちゃんの年齢は" + mafuyu.age + "歳だよ!"); System.out.println("まふゆちゃんのコスチュームは" + mafuyu.costume + "だよ!"); System.out.println("まふゆちゃんの髪色は" + mafuyu.hairColor + "だよ!"); System.out.println("まふゆちゃんのパンツの色は" + mafuyu.pantyColor + "だよ!"); } }
実行すると以下のように表示されるはずです。
「public」って奴がいきなり現れてきたけどなんぞや??って思いますよね。
実はこいつが「アクセス修飾子」のひとつ、public(パブリック)なのです!!
publicが付けられたフィールドやメソッドは、クラスの内部、外部問わずどこからでも自由にアクセスすることができます。
今回の例の場合、Mafuyuクラス内で定義されているフィールド
・age(年齢)
・costume(コスチューム)
・hairColor(髪色)
・pantyColor(パンツの色)
は全てpublicになっているので、mainメソッドからこれらの値にアクセスして、System.out.println()で画面表示することができるわけです。
Mafuyuさんが「コイツを見ろ!!」と言わんばかりに、外部に大公開しているようなイメージでしょうか。
でもちょっと待って下さい!!
どう見ても、外部に見られてはまずいフィールドがひとつありますよね。
そう、pantyColor(パンツの色)です!!
このままでは私がお嫁に行けなくなってしまいますね。
どうにかして、私のパンツの色を外部から知られないように隠してあげましょう。
ここで必要になるのが、private(プライベート)と呼ばれるアクセス修飾子です。
名前からなんとなく察しがつくと思いますが、このprivateがついたフィールドやメソッドは、自身のクラス内部からのみアクセス可能になります。
すなわち、Mainクラスのような外部クラスからアクセスすることができなくなります。
pantyColor のアクセス修飾子を、publicからprivateに変更しましょう。
public class Mafuyu { public int age = 17; public String costume = "セーラー服"; public String hairColor = "シルバー"; private String pantyColor = "水色"; // アクセス修飾子をprivateに変更! }
この状態でMafuyu.javaを保存してから、Main.javaを開いてみてください。
なんかエラーが出て実行できないはずです。
Mafuyu.pantyColor is not visible.
すなわち、「まふゆちゃんのパンツの色が見えません」ってことです。
privateなフィールドやメソッドに外部からアクセスしようとすると、こんなふうにエラーになって実行できません。
これがアクセス修飾子「private」のもつ力です。
今回覚えてほしいアクセス修飾子は「public」「private」の2種類。
・public : 外部に見せたいものにつけるアクセス修飾子。
・private: 外部に見せたくないものにつけるアクセス修飾子。
というふうに覚えてください。
ひとまず、アクセス修飾子に関する説明は以上です。
特に難しくはないでしょ?
【補足】
前回の記事の内容をしっかり覚えている賢い人は、
「フィールドにpublicなんか付けなくても普通に外部からアクセスできたよな…?」
「"public"と"アクセス修飾子なし"って一緒なんじゃ…?」
と思っているかもしれません。
確かにちょっと似ているのですが、「public」と「アクセス修飾子なし」は違います。
詳しく説明したいところだけど、今回説明したい内容からちょっと逸れてしまうので、興味がある人はこの記事を読み終わったあとに自分で調べてみてね。
スポンサーリンク
■ カプセル化の具体的なメリットは?
さてさて、アクセス修飾子については理解してもらえたと思うので、今回の記事の本題である「カプセル化のメリット」についての解説を始めていきましょう。
ここが今回の記事における一番の大事なポイントになるので、じっくり読んでください!!
「カプセル化」の本質は「他人への思いやり」だって記事の冒頭で書きましたよね。
この「思いやり」ですが、具体的にどういうことかというと
「ごちゃごちゃした難しいものは外部に見せないようにして、本当に必要なものだけを外部から見えるような親切設計にする」
ということです。
こうすることによって、使用者にとってシンプルで使いやすいクラスが完成します。
これをさっき説明した「アクセス修飾子」を使って言い換えると、
「クラス内のデータはできる限りprivateにして、外部から必要とされているものだけをpublicにする」
ということになります。
実際に「カプセル化」の考えが役に立つ例を挙げてみましょう。
【例1】
クラス内に「外部から書き換えたらバグってしまうフィールド」があったとします。
「カプセル化」が適切に行われていないクラスでは、このフィールドのアクセス修飾子がpublicになっています。
これをprivateにすれば、外部からの書き換えは不可能になるので、未然にバグを防ぐことができます。
【例2】
1000件のpublicメソッドがあるクラスを想像してみてください。
これらのうち、実際に外部から使う必要があるのは5件のみで、他995件はクラス内部でしか使いません。
このクラスに対して「カプセル化」を適切に行うと、クラス内部で使う995件のメソッドは全てprivateになります。
こうすることによって、クラスの使用者は1000件のメソッドの中から自分が使いたいものをわざわざ探す必要はありません。
そもそも5件しか見えないので、自分が使いたいメソッドをすぐに見つけることができます。
とまあ、こんな感じのメリットがあります。
「カプセル化」とは、このように「外部にとって不要な情報を隠す」ことを「カプセルの中にしまう」という事象に例えた言い回しなのです。
スポンサーリンク
■ フィールドは全て隠すのが基本!
以下のコードを見てください。
先程書いてもらったMafuyuクラスとMainクラスです。
public class Mafuyu { public int age = 17; public String costume = "セーラー服"; public String hairColor = "シルバー"; private String pantyColor = "水色"; }
public class Main { public static void main(String[] args) { Mafuyu mafuyu = new Mafuyu(); System.out.println("まふゆちゃんの年齢は" + mafuyu.age + "歳だよ!"); System.out.println("まふゆちゃんのコスチュームは" + mafuyu.costume + "だよ!"); System.out.println("まふゆちゃんの髪色は" + mafuyu.hairColor + "だよ!"); System.out.println("まふゆちゃんのパンツの色は" + mafuyu.pantyColor + "だよ!"); } }
これらのコードは一見問題なさそうですが、実はとってもお行儀が悪いコードなのです!!
「カプセル化」の考え方では、「フィールドは可能な限り全てprivateにする」というのが基本になります。
パンツの色のように見られたら恥ずかしい値でも、そうでない値でも、フィールドは「外部に見せるべきではない」なのです。
ここも大事なポイントなので、覚えておいてくださいね。
「フィールドは可能な限り全てprivate」にするのです。
カプセル化の考え方に従ってMafuyuクラスを変更すると、以下のようになります。
public class Mafuyu { private int age = 17; private String costume = "セーラー服"; private String hairColor = "シルバー"; private String pantyColor = "水色"; }
Mafuyuクラスの変更を保存したら、Mainクラスを見てみましょう。
当然ですが、エラーだらけで実行できません。
では、Mainクラスからこれらのフィールドにどうやってアクセスすればいいのでしょうか…?
オブジェクト指向プログラミングにおいて、外部からこのようなprivateなフィールドにアクセスするときには、getterメソッド/setterメソッドというものを使うことが推奨されています。
長くなってしまったので、これらについては次回の記事で説明することにしましょう。
今回はここまで!!
■ 全部publicじゃダメなの…??
最後にちょっとだけ補足。
「privateにするよりも、全部publicにしちゃったほうがどこからでもアクセスできて便利じゃない…?」とか思ってませんか?
実はその考え方、オブジェクト指向プログラミングでは好ましくないとされています。
というか、オブジェクト指向に限らず、「どこからでもアクセスできるようにすること」はプログラミングを行う上でよろしくない考え方です。
「どこからでもアクセスできる状態(public)にする」というのは、あなたが考えている以上に危険で、責任が伴う行為なのです。
自由にどこからでも値を書き換えることが可能だと、思わぬバグの発生源になるし、バグの原因を突き止めるのも大変です。
詳しいことは他の人の記事とかを参考にしてほしいのですが、とにかく初心者のうちは「何でもかんでもpublicにするのはダメ!!」とだけ覚えておいてください。
■ まとめ
・「カプセル化」の本質は「他人への思いやり」だよ!
・「public」は外部に見せたいもの、「private」は外部に見せたくないものにつけるアクセス修飾子だよ!
・「外部から必要とされているもの」だけをpublicにして、それ以外は全てprivateにすべきだよ!
・「外部に見せる必要がないもの」をprivateにすることで、シンプルで使いやすいクラスが完成するよ!
・フィールドは全てprivateにするのが基本だよ!
・何でもかんでもpublicにするのは危険だからやめたほうがいいよ!
次回以降は、privateなフィールドにアクセスするために必要なgetterメソッド/setterメソッドの使い方と、それらの存在意義について解説したいと思います!!
お楽しみに~!!
ではでは~・:*+.\( °ω° )/.:+