オブジェクト指向の「カプセル化」とはなにか?超わかりやすく解説します!
こんにちは!
現役Webエンジニアの今井(@ima_maru)です。
プログラミングについて勉強していると、「オブジェクト指向」というキーワードをよく聞きませんか?
これは、ひと昔前のプログラミング手法と異なり、「モノが自主的に作用しあう形でプログラムを組むというようなプログラミング手法」などと言われます。
「こんな難しく言われてもわかんねえよ!」「なに言ってんだよ!」って方。私もそうでしたのでご安心ください。
私はこの概念をしっかりと理解するのに一か月くらいはかかりました。プログラミング初心者にとって、そのくらい理解が難しいものであるということは確かです。
大まかに言って、オブジェクト指向を構成する要素は「継承」「カプセル化」「ポリモーフィズム」の3つがあります。これら3つはオブジェクト指向の基盤を担っているものです。オブジェクト指向を理解するならば避けては通れない道でしょう。
ポリモーフィズムについては以下の記事で解説しているので、是非こちらも併せてごらんください。
今回はその中でもデータを保護する役目とされる「カプセル化」について解説します。
皆さんにより効率的に理解してほしいという想いから、初めてプログラミングを学ぶ方にも優しい言葉で、できるだけわかりやすく解説していこうと思います。
カプセル化を理解するには、ざっくりとカプセル化というのがどのようなものなのかというのを知ってから、カプセル化の狙いやメリットを知るという順に学習したほうが理解が深まると思いますので、その順で解説していきます。
- カプセル化というのがどのようなものなのか
- カプセル化の狙いやメリット
それでは、オブジェクト指向の3つの特徴の1つのカプセル化というのはどういうものなのでしょうか。
見ていきましょう!
オブジェクト指向におけるカプセル化(encapsulation)とは?
カプセル化とは、オブジェクトの情報を隠蔽することによって、不整合を引き起こすような操作をできなくさせる仕組みです。
今となっては「よく表現できてるなあ」と思いますが、初めにこんなこと書かれても「そんなこと言われてもわかんねえよ!」って思うでしょう。そのような方向けに解説していくのでご安心ください。
カプセル化のイメージ
カプセル化とは、オブジェクトやデータをカプセルのように保護するという意味から来ています。
カプセルというと、どのようなものをイメージしますか?
- 外から防御されている
- 包まれている
一般的なのは、カプセル状のお薬をイメージする人が多いのではないでしょうか。プログラミングにおいてのカプセル化もそのようなイメージです。
では何を包んで何から守るのか?
すごく簡単に言えば、「オブジェクト内のデータ」を包み「オブジェクト外からの不正アクセス」から守るというのが答えになります。イメージはこんな感じ。
要は、オブジェクト外からのデータアクセスを拒否するのです。
これらのデータアクセスの可否はアクセス指定子と呼ばれるものによって決められます。実際に、アクセス指定子によってカプセル化がどのように行われるのかを見てみましょう。
アクセス指定子とカプセル化
カプセル化はデータを保護する役目といいましたが、具体的にはどういうことをするのでしょうか?
- 実際にどのように保護するのか?
- 保護をするとどのようなことができなくなるのか?
こういったところを疑似言語を使って解説していきます。まず以下のようなコードを用意しました。
クラスA {
[保護されている] データ1;
[保護されていない] データ2;
};
この状態だと、データ1は保護されていて、データ2は保護されていないデータになります。
データ1は保護されている → カプセル化されている
データ2は保護されていない → カプセル化されていない
実際のプログラミング言語だと「private」「public」などのアクセス指定子を用います。
class A {
private: int data1;
public: int data2;
};
ここで、保護されていない状態と保護されている状況は何が違うかというと、「クラス≒オブジェクト外からのデータへのアクセスができるかできないか」が違います。
メイン文 {
クラスA オブジェクトX;
オブジェクトX.データ1 = 12; // ×アクセス不可
オブジェクトX.データ2 = 34; // 〇アクセス可能
}
データ1はカプセル化によって保護されているためオブジェクト外からのアクセスができません。一方データBは保護されていないためアクセスができます。
実際、プログラミング言語C++で書くとこんな感じになります。
int main() {
A X;
X.data1 = 12; // ×アクセス不可
X.data2 = 34; // 〇アクセス可能
}
もう一度言うようですが、カプセル化されているデータに対してはメイン文などの外からのアクセスができないようになります。
アクセスができなければ、データを変更することができません。
「使えないなら意味ないのでは」と思いませんか? しかし、オブジェクト外からでもカプセル化されたデータを変更する方法が存在します。
それは、クラス≒オブジェクト内に保護されていない関数を作って、その関数によってデータを変更してもらうという方法です。
カプセル化はこれとセットで使われます。簡単な例を挙げてみましょう。
- まず、「生徒」というクラスを作り「名前」を持たせます。
- そして、この「名前」はカプセル化して、直接的な変更はできないようにします。
- 最後に「改名」という名前を変更する関数をクラス内に用意します。この関数は外からのアクセスもできるように保護しないでおきます。
クラス 生徒 {
[保護されている] 名前;
[保護されていない] 改名(新しい名前) { 名前 = 新しい名前 };
}
メイン文{
生徒 生徒1;
生徒1.名前 = "田中 太郎"; // ×アクセス不可
生徒1.改名("田中 太郎"); // 〇アクセス可能
}
このように、クラス内にカプセル化されていない「改名」という関数を作り、それを経由して名前を変えてもらう形にします。
こうすれば、カプセル化された変数にも間接的にアクセスすることができますね。
でもまだ疑問が残ります。
「カプセル化を使ってデータの直接変更ができなくする。」
「関数を使って間接的なデータ変更ができることも分かった。」
「なんでデータを直接変更しちゃダメなんだ???」
そうなんです。私はこの「カプセル化をする意味」の理解に相当な時間が掛かりました。
では、なぜカプセル化をしてデータのアクセスをクラス内だけに限定するのでしょうか?
主人公の体力を使ってメリットとともに解説していきます。
- オブジェクトのデータが外から直接変更されることを禁止する
- アクセス指定子によってカプセル化するかしないか決められる
- カプセル化されているデータはクラス内の関数によって変更できる
カプセル化の狙いとメリット
カプセル化の狙いは「データを保護する」ということです。それに尽きます。
データの変更をオブジェクト自身に任せることによって、バグ(不整合)を引き起こさせないようにすると言ったりもします。
先ほど学んだように、カプセル化を用いれば、クラス≒オブジェクト内の関数を一度経由させないといけない状態を作れます。
この関数に不正なデータ変更を禁止する条件や設定を設ければ、データのバグを防げます。要は、
- 直接データを操作させずに、一度関数を通す状況を作る
- この関数に条件や設定を設けることで、不正なデータ操作を防ぐ
こんな感じのイメージです。
カプセル化のわかりやすい例!主人公のHPをカプセル化する?
まずは、主人公のもとになるクラス「ユニット」を作りましょう。
クラス ユニット{
[保護されていない]
MAX_HP = 80; // 最大の体力
HP = 50; // 現在の体力
};
このクラスには「最大の体力」「現在の体力」を持たせました。
初期値はMAX_HP 80とHP 50に設定しました。
まずは主人公のオブジェクトを作りましょう。
メイン文{
ユニット 主人公;
...
これで今、クラス「ユニット」をもとに作られた主人公というオブジェクトができました。
体力の初期値は以下のようになっています。
HP 50/80
ではこの状態から主人公の体力を変更していきましょう。
まずは、主人公の現在の体力に「直接50を足す」という処理をしてみましょう。
主人公.HP += 50; // →[HP100/80]
そうしたら現在の体力が最大の体力を超えてしまいました。
このような最大体力を超える表記を許しているゲームもありますが、これを許していないゲームではこれらを一般的にバグ(不整合)と言います。
逆に、主人公の現在の体力から「直接200を引く」という処理をしてみましょう。
主人公.HP -= 200; // →HP[-100/80]
今度は現在の体力が0を下回ってマイナスの値をとってしまいました。これもバグの一種です。
これらのバグは直接データを操作したことが原因です。
- 体力の値を直接操作
- 適正値を超え体力が異常値に
なら直接データを操作できなくさせましょう。カプセル化の出番ですね。
まずはデータを保護=カプセル化をしてみましょう。
クラス ユニット{
[保護されている]
MAX_HP = 80; // 最大の体力
HP = 50; // 現在の体力
}
このようにすると、現在の体力や最大の体力はメイン文やオブジェクト外からは操作できなくなります。
でもこれだとデータの変更ができないので、体力を変更できる関数を作りましょう。
クラス ユニット{
[保護されている]
MAX_HP = 80; // 最大の体力
HP = 50; // 現在の体力
[保護されてない]
体力の増減(値) {
HP += 値;
if (HPが0以下なら) HP = 0;
if (HPがMAX_HP以上なら) HP = MAX_HP;
}
}
このようにすると、現在の体力を変更するときは、一度「体力の増減」という関数を経由して変更される形にすることができます。
しかも、体力の増減の関数では、条件分岐により体力が0からMAX_HPまでしか設定できなくなっています。ここがすごい重要。
「体力の増減」関数に「+1000」という値を送っても、最大の体力を超えることはありえません。
逆に「-1000」を送っても0を下回りません。
先ほどのバグが防げていると思えませんか?
カプセル化とは、オブジェクトのデータを外からアクセスできなくして保護することを言います。
データに変更を加えるときは、オブジェクト自身が持っている関数にアクセスしてそれによって変更を加えるため、仮に異常なデータ変更が来た場合、適切な値に戻したり、変更を拒否することもできます。
こんな風に、オブジェクト自体が自らのデータを変えるようなプログラミング方法が、オブジェクト指向プログラミングのイメージにとても近いです。
重要なのは、「オブジェクト自体が」という部分と「オブジェクト」という概念です。
これらの理由より、カプセル化はオブジェクト指向の三本柱の一つなのです。
カプセル化のメリットとは?
カプセル化はこのHPが上限値を超えてしまわないようなプログラム設計からもわかる通り、
情報を直接操作することをできなくして情報が壊れてしまうことを防止する
こんな役目を担っています。
オブジェクト自身に適切な情報操作を委ねるというのがポイントとなります。
【もっと早く知っておけばよかった...。】情報系を学んでいる学生におすすめのサービス!
おすすめのオンライン学習サービス一覧!【基本無料・超初心者~上級者向けまで】
プログラミングやコンピューターサイエンスを効率的に学ぶには、オンライン学習サービスを利用するのが良いでしょう。
というより、使わなきゃ勿体ないですよ!
基本的に無料のサービスが多いですし、月額制のサービスでも1,000円~3,000円程度とかなりリーズナブルです。
オンライン学習サービス | おすすめ度 | 対象者 | 特徴 |
---|---|---|---|
Progate | 超初心者 | プログラミング入門・基本無料 | |
Udemy | 初心者~中級者 | 豊富な動画教材・セールでお得・教材購入 | |
侍エンジニアPlus | 初心者~中級者 | 現役エンジニアに質問できる環境・月額制 | |
Paiza | 初心者 | 競プロ入門・就活/インターン・無料 | |
ドットインストール | 初心者 | 動画教材・成果物ができる・基本無料 | |
Recursion | 初心者 | コンピュータサイエンス基礎・基本無料 | |
AtCoder | 中級者~上級者 | 競技プログラミング・アルゴリズム・無料 | |
Kaggle | 中級者~上級者 | AI・データサイエンス・競プロ・英語・無料 |
情報系を学んでいる学生におすすめなオンライン学習サービスに厳選しました。
ぜひ気になったサービスを始めてみてください!(その一歩が、1年後や2年後にものすごく大きな一歩になっているはずです。)
僕が実際に使ったのは、Progate➡Paiza➡AtCoder➡Udemyです。Kaggleもちょっとだけ。そのほかのサービスもとても魅力的です。
レバテックルーキー【ITエンジニアを目指すならここが最強】
レバテックルーキーは、ITエンジニア志望の学生におすすめの就活エージェントです。
レバテックルーキーのサービスを受ける条件は以下の2点です。
- 大学生・大学院生・専門学生・高専生・短大生である【文系・理系・情報系は問わない】
- ITエンジニア志望・もしくは興味がある
この条件に当てはまる方は、ぜひとも早めに登録することをおすすめします。(就活は早めにはじめると超有利になります。)
\ カウンセリング~内定まで"全て無料"! /
実際に僕もレバテックルーキーで最終内定を決めました。質の高い企業紹介と就活サポートが魅力の最強就活エージェントです。(ガチでオススメ!)
レバテックカレッジ【大学生専用のプログラミングスクール】
レバテックカレッジは、大学生・大学院生専用のプログラミングスクールです。
- プログラミングを学んだことがない。授業は受けたが、スキルに不安がある。
- 短期間で、Web企業に求められるレベルのスキルを習得したい。
- 大学に通いながら、就職活動を進めながら、並行して自分のペースで学びたい。
こういった方におすすめのプログラミングスクールです。
本気で学ぶならプログラミングスクールが効率的です。学生のうちに実務レベルのスキルを身に着けられれば、希少性の高い人材になれます。
オブジェクト指向におけるカプセル化|まとめ
オブジェクト指向3大要素の一つともされる「カプセル化」をできる限りわかりやすく説明したつもりですが、どうでしたでしょうか?
- カプセル化とは?
- オブジェクトの情報を隠蔽することによって、不整合を引き起こすような操作をできなくさせる仕組み
- (かみ砕くと)オブジェクト外からの不正アクセスを拒否してオブジェクトを保護すること
- なんでカプセル化するの?
- データの変更をオブジェクトが用意した関数を通さないといけなくできる
- 関数にエラーやバグを起こさない仕組みを作ることで、バグを防げる
カプセル化というのは、最初聞いたとき「なんで情報を隠す必要があるんだ?」と思いましたが、C++を学習していくうちに少しずつ理解が深まりました。
この記事を見て「なるほどなぁ、そういうことか」と思ってくださる方がいれば、とても嬉しいです。
以上「カプセル化とはなにか?超わかりやすく解説します!」でした!
最後までご覧いただきありがとうございます。