オブジェクト指向とは?メリットは?例を使ってわかりやすく解説!
プログラミングの勉強をしていて、「このプログラミング言語はオブジェクト指向です」などといった言葉を見かけませんか?
こんにちは!今井(@ima_maru)です。
私がこの「オブジェクト指向」という言葉に出会ったのは、大学のプログラミング言語「C++」の授業でした。
教授はオブジェクト指向のことを、
- 「モノ」を主体として考える
- 三本柱は「継承」「カプセル化」「ポリモーフィズム」
- 手続き型に変わって、現在主流のプログラミング手法
などと言ってましたが、当時は「ちょっと何言ってるかわかんない」状態でした。
なので、過去の自分にわかりやすく説明する気持ちで、
- プログラミングを学び始めた方でもわかるように
- できるだけ丁寧に簡単な言葉で
- そして具体的に
「オブジェクト指向」とは何なのかを解説しようと思います。
この記事では以下の疑問について解説します。
- オブジェクト指向ってどういう意味?
- カプセル化、継承、ポリモーフィズムってなに?
- メソッドって?
- どんなメリットがあるの?
- 手続き型言語との違いは?
それでは解説していきます。
オブジェクト指向を理解する
まず初めに、オブジェクト指向はこれだ!という明確な定義はないとおもって大丈夫です。
なので、解説が難しく、理解もすぐにできるものではないのだと思います。
本記事では、以下の順番で解説をしていこうと思います。
- オブジェクト指向プログラミングの簡単な説明
- オブジェクトとは何か
- 自動車を使ったオブジェクト指向プログラミングの解説
- オブジェクト指向プログラミングのメリットとは何か
そして最後にオブジェクト指向をサポートしているプログラミング言語、すなわち「オブジェクト指向言語」と呼ばれるプログラミング言語達を紹介します。
オブジェクト指向プログラミングとは?
オブジェクト指向プログラミング(Object Oriented Programming)とは、
プログラムをカスタマイズ可能な部品の組み合わせとして表現する考え方のプログラミング手法
です。かみ砕いていうと、
「様々なパーツを作って、それを組み合わせるという方針でプログラムを組みましょう」
というプログラミングの手法です。
つまり、一つの「プログラミングのやり方」や「プログラムの組み立て方」です。
「あるシステムを作るためにどのようなアプローチ、方法でプログラムを作っていくか」
このアプローチの仕方の話なんです。
現在の主流となっている方針がこの「オブジェクト指向プログラミング」です。
どういう方針かというと、「カスタマイズ可能な部品の組み合わせとして表現する」ということです。
では、「カスタマイズ可能な部品」とは何でしょうか?
それが「オブジェクト」という概念になります。
カスタマイズ可能な部品「オブジェクト」とは?
オブジェクト指向プログラミングとは、プログラムをカスタマイズ可能な部品の組み合わせとして表現する考え方といいましたが、
この「カスタマイズ可能な部品」が「オブジェクト」という概念になります。
つまりオブジェクト指向プログラミングを言い換えれば、
プログラムをあらゆる「オブジェクト」の組み合わせで表現しよう
という手法ということになります。
ではオブジェクトとはどういう概念なのでしょうか?
「オブジェクト」とは、私たちが生きていて当たり前のように感じる概念「モノ」です。
- リンゴ
- パソコン
- 自動車
すべて「モノ」「オブジェクト」です。
当たり前のことです。
この当たり前の「モノ」の考え・概念をプログラミングに落とし込もうと考えたのです。
これがとても抽象的でオブジェクト指向という言葉の明確な定義がないということにつながります。
この「オブジェクト」の大事な要素は2つあると思っています。
それが、
- オブジェクトはオブジェクトで構成することもできる
- オブジェクトの操作はオブジェクト自身に任せる
という2つです。
オブジェクトはオブジェクトで構成することもできる
オブジェクトはオブジェクトによって構成することもできます。
例えば、パソコンもオブジェクトですが、パソコンの部品たちもそれぞれオブジェクトとしてとらえることができます。
つまり、パソコンというオブジェクトを構成している部品たちもまたオブジェクトなのです。
もっと細分化してみれば、その部品たちもいろんな部品から作られているということになります。
オブジェクトの操作はオブジェクト自身に任せる
オブジェクトは自主的に作用します。
もっと簡単に言えば、オブジェクトは自分で動いたり性質を変えたりできるということです。
例えば、自動車に乗っていてもっとスピードを上げたいと思ったらどうしますか?
アクセルペダルを踏めばいいですよね。
変な言い方ですが、自動車はアクセルペダルを踏めば自動車自体が速度を上げてくれます。
決して、私たちが車の速度を直接操ってるわけではないんです。
ほとんどの内部の処理などを自動車というオブジェクトにゆだねているのです。
これってすごいことですよ。
だって車に乗っている皆さんのほとんどの方は、車の内部の処理を詳しく知らずに車を運転しているんですから。
知らなくても乗れる。
これがオブジェクト指向プログラミングのメリットとても良く似ています。
自動車というオブジェクトを作る
ここで、簡単に自動車というオブジェクトをプログラムで表現してみます。
まず、オブジェクトを作るには「クラス」と呼ばれる設計書が必要です。
なので、まずは自動車のクラスを作ります。
class Car {
//自動車の速度
int speed;
public:
// アクセル
void accelerate(int size);
// スピード表示
void show_speed();
// おまじない
Car();
};
これを利用してあるプログラムを作りました。
内容はよくわからなくて大丈夫です。
int main()
{
// Carオブジェクトを作成
Car carX;
// 初期スピードを表示
carX.show_speed();
// 入力を受け取る変数
int size = 0;
// 5回ループ
for (int i = 0; i < 5; i++)
{
// 入力を受けとる
cout << "アクセルペダルの踏み込み量(0~100%)->";
cin >> size;
// carXのアクセルに入力を渡す
carX.accelerate(size);
// carXの速度を表示
carX.show_speed();
}
// 終了のおまじない
return 0;
}
このプログラムを実行すると、
初期速度:0km/h
アクセルペダルの踏み込み量(0~100%)->
このような画面が出てきます。
ここで入力を5回受け付けます。
入力は「アクセルペダルをどのくらい踏み込むか」を0~100%の値で設定します。
では「アクセルペダルをどのくらい踏み込むか」を、
- 10(%)
- 30(%)
- 50(%)
- 50(%)
- 100(%)
この順に入力してみます。
そうすると、
初期速度:0km/h
アクセルペダルの踏み込み量(0~100%)->10
速度:6km/h
アクセルペダルの踏み込み量(0~100%)->30
速度:16km/h
アクセルペダルの踏み込み量(0~100%)->50
速度:30km/h
アクセルペダルの踏み込み量(0~100%)->50
速度:44km/h
アクセルペダルの踏み込み量(0~100%)->100
速度:64km/h
このように表示されました。
どうでしょうか?
- 10%アクセルペダルを踏みこめば、6km/h速度が上がりました。
- 30%アクセルペダルを踏みこめば、10km/h速度が上がりました。
ここで大切なことは、「アクセルペダルを踏むことで自動車が勝手に速度を上げてくれたこと」です。
皆さんはアクセルペダルをどれくらい踏むかというのを指定すれば、あとはオブジェクトが勝手に速度を調節してくれます。
こんな風に、皆さんは中の詳しい処理を知らなくても使い方さえわかれば正しく使えるんです。
これって一つの独立したパーツのように思えませんか?
こういうパーツを複数人で作っていって最後に組み合わせれば自動車という一つの大きなオブジェクトが作れるのです。
ちなみに私がアクセルペダルとして書いた処理は以下のコードです。
void Car::accelerate(int size)
{
if (size < 0) return;
if (size > 100) size = 100;
size = 2 * sqrt(size);
speed += size;
if (speed > 100)
speed = 100;
}
概要は、
- もらった値が範囲外の時は特殊な処理をする
- もらった値の2乗根を取り2倍して速度に足す
- 速度が100を超えないように設定
ということをしていました。
この処理を知らなくてもちゃんと動作したっていうのが大事なわけです。
これと同様に「ブレーキ」「ハンドル」という様々な処理をいろんな人に作ってもらえばいいんです。
そして最後に合わせて一つの自動車っていうオブジェクトを作るのです。
こんな風に、
プログラムの(独立した)パーツを各自で作り上げていって、最後に組み合わせよう
と考えるのがこのオブジェクト指向プログラミングということになります。
完成系は以下のような感じでしょうか?
class Car {
Performance performance; // 車の性能
string number; // ナンバー
Light light; // ライト
double speed; // スピード
double gas; // ガソリン残量
public:
Car();
bool start_engine(); // エンジンをつける
bool stop_engine(); // エンジンを切る
bool change_gear(int gear); // ギアを変更する
void accelerate(double size); // アクセル
void brake(double size); // ブレーキ
void turn(double size); // 曲がる
string get_number(); // ナンバー取得
double get_speed(); // スピード取得
double get_gas(); // ガソリン残量取得
};
これらの部品を作っていくというわけですね。
ここからはオブジェクト指向プログラミングを取り入れると、
- プログラマにとってどんなメリットがあるのか?
- 開発がどうスムーズになるのか?
という、メリットの面を解説していきます。
オブジェクト指向プログラミングのメリット3選
大規模なプロジェクト・多人数の開発で活躍する
オブジェクト指向プログラミングは、多人数開発に適しているプログラミング手法です。
オブジェクト指向は、メインプログラムをカスタマイズ可能な部品(プログラム)の集まりとして構成するので、部品一つ一つの開発を多くの人に分配することができます。
- Aさんはアクセルの関数を作って
- Bさんはブレーキの関数を作って
このように役割分担を明確にすることができるので、多人数での開発においては必須といえる手法となってきています。
変更に強い柔軟性
オブジェクト指向プログラミングは、変更に強いプログラミング手法です。
設計は難しいものの、一度プログラムが完成すれば変更は比較的簡単です。
例えば、車のタイヤだけ変更したいのならば、タイヤだけ変更すればいいのと同じです。
クラスやオブジェクトの一部分を変えるだけで済むというわけです。
逆にオブジェクト指向でないと、メインプログラムの様々な場所で変更点が出てくるといったことも少なくありません。
そうすると一から作り直さないといけないといったことも起こりかねません。
コードの再利用により記述量が減る
オブジェクト指向プログラミングは、コードの再利用が多く使われるプログラミング手法です。
なので、同じコードを何回も用いるようなプログラムではその効力を最大限に発揮します。
変えたい部分を変えたり、付け加えたり、なくしたりもできます。
ほかにも様々なメリットがあると思いますが、私はこの3つ大きいメリットだと思います。
オブジェクト指向を実現するための機能
オブジェクトの設計書である「クラス」
まずこれがないと話になりません。
クラスとは、オブジェクトのもとになる設計書です。
一つの「モノ」の性質や操作を記述します。
プログラミングでいえば、中に書くのは変数と関数です。
変数が「モノ」の要素を、関数が「モノ」の操作を担当します。
クラスの持つ変数と関数は特殊な呼び方がされます。
変数を「メンバ変数」「メンバ」「フィールド」などと呼び、
関数を「メソッド」「メンバメソッド」「メンバ関数」などと呼びます。
プログラミング言語C++で書いた車のクラスはこんな感じです。
class Car // 車の設計図をあらわしたクラス「 Car 」
{
private:
int weight; //「重量」をあらわしたメンバ変数
int speed; //「スピード」をあらわしたメンバ変数
int number; //「ナンバー」をあらわしたメンバ変数
public:
void accelerate(int size); //「アクセル」をあらわしたメソッド
void brake(int size); //「ブレーキ」をあらわしたメソッド
void turn(int size); //「曲がる」をあらわしたメソッド
};
クラスの一番の特徴は、クラス内に関数を持つことができる点です。
オブジェクトの操作である「メソッド」
クラスが持っている関数を「メソッド」「メンバメソッド」「メンバ関数」などと言います。
車でいえばアクセルやブレーキなどにあたります。
アクセルペダルを踏めば加速し、ブレーキペダルを踏めば減速してやがて止まります。
メソッドは自分自身を参照して自分の要素を変えることができます。
先ほどのアクセルペダルを表現したメソッドに、「アクセルペダルをどのくらい踏んだかの値」を渡してあげれば、その車が勝手に速度を上げたように見せることができます。
「モノ」が自主的に作用したようにできるのです。
メソッドは、オブジェクト指向のプログラミング言語には欠かせない機能です。
継承(inheritance)
継承とは、あるクラスを引継ぎ、新たなクラスを作成できる機能のことです。
継承したクラスを修正したり追加したりもでき、オリジナルを保護する機能も含みます。
簡単に言うと、一回使ったオブジェクトの要素と操作を引き継げるよってことです。
※記事調整中
カプセル化(encapsulation)
カプセル化とは、オブジェクトの情報を隠蔽することによって、不整合を引き起こすような操作をできなくさせる仕組みです。
簡単に言ってしまえば、アクセス権の付与です。
オブジェクトに関するデータを自ら操作するときは、そこにアクセスするだけの権利がないとできないようになっています。
管理者権限などをつけることによりシステム的にヤバイことを防ぐみたいなイメージです。
カプセル化はプログラミングにおいてこのような役割を担っています。
ポリモーフィズム(polymorphism)
ポリモーフィズムとは、オブジェクトなどのデータ型に関する操作が統一的であることである。
日本語では多様性などと訳されます。
人気のオブジェクト指向プログラミング言語一覧
オブジェクト指向プログラミング言語と呼ばれるものは、純粋なオブジェクト指向を実現したものではないものです。というのも、手続き型とオブジェクト指向を組み合わせたものなど、オブジェクト指向を取りいれたものがほとんどです。
Python
Python(パイソン)は人工知能(AI)の分野に強い言語です。
Ruby
Rubyは日本人(まつもとゆきひろ氏)が開発したWeb系に強いプログラミング言語です。
PHP
HTMLやCSSと一緒によく使われる、人気の高いオープンソースの汎用スクリプト言語です。
Java
とても人気の高いプログラミング言語のひとつです。
JavaScript
HTML、CSSとともにWebサイト開発に欠かせないオブジェクト指向のスクリプト言語です。
C++
C言語にオブジェクト指向を足したような言語です。
人気のプログラミング言語についてはこちらの記事で詳しく書いているので興味のある方はお読みください。
最後に
オブジェクト指向とはプログラミング言語を表すときによく使われる単語です。
しかし、これからプログラミングを学ぶ方にとって、そんなの知らないよという方が多いんじゃないかと思います。そんな方のために、ざっくりとこの概念をつかんでほしいというのがこの記事の一番の目的です。
最後まで読んでいただきありがとうございます。