オブジェクト指向を学ぼうとすると、クラスや継承など横文字が多くてとっつきにくく感じる人も多いと思います。
本記事では「身近な具体例」と「図解イメージ」を使いながら、オブジェクト指向の考え方を直感的に理解できるように解説します。
専門用語を最小限にしつつ、C言語風のサンプルコードも交えて説明しますので、プログラミング初心者の方でも安心して読み進めてください。
オブジェクト指向とは何かをイメージでつかむ
ものごとを「部品」としてとらえる考え方

オブジェクト指向は「現実世界のものごとを、そのままプログラムの部品として扱おう」という発想です。
現実には車や人、犬、スマホなど、たくさんの「もの」が存在します。
それぞれは次の2つを持っています。
1つは状態です。
車なら色や速度、人なら名前や年齢など、数値や文字で表せる情報です。
もう1つはふるまい(操作)です。
車なら走る・止まる、人なら歩く・話す、スマホなら電話する・写真を撮るなどの「動き」です。
オブジェクト指向では、状態とふるまいをセットにした「かたまり」をオブジェクトと呼びます。
プログラム全体を、こうしたオブジェクトの組み合わせとして設計していくのがオブジェクト指向の基本的な考え方です。
クラスとオブジェクトを「設計図」と「実物」で考える
クラスは「設計図」、オブジェクトは「完成品」

オブジェクト指向ではよく「クラスは設計図、オブジェクトは製品」というたとえを使います。
- クラス
プログラムの中で「こういうオブジェクトを作る」という型(テンプレート)を表します。
どんな状態(データ)を持ち、どんなふるまい(操作)ができるかを定義します。 - オブジェクト
クラスという設計図から実際に作られた実体です。
クラスを基に、色や名前など具体的な値が入ったものがオブジェクトです。
車を例にすると、「車という種類」= クラス、「赤いスポーツカー」「青い軽自動車」= オブジェクトというイメージです。
カプセル化とは「中身を隠して使いやすくする」こと
リモコン家電でイメージするカプセル化

カプセル化は、オブジェクトの中身を見せすぎず、必要な操作だけ公開する仕組みです。
テレビを思い浮かべてください。
私たちはテレビの内部の基板や信号処理について何も知らなくても、リモコンの電源ボタンや音量ボタンだけで操作できます。
テレビは
- 内部の複雑な仕組みは隠す
- 外から使える操作だけをボタンとして提供する
という設計になっています。
これがプログラムの世界でいうカプセル化に相当します。
カプセル化により、「どうやって実現しているか」ではなく「何ができるか」に集中してコードを書けるようになります。
これにより、プログラムの見通しが良くなり、修正もしやすくなります。
具体例で見るオブジェクト指向の考え方
「犬オブジェクト」で状態とふるまいを整理する

身近な例として、犬をオブジェクトとして考えてみます。
犬には、次のような状態があります。
- 名前
- 年齢
- 体重
また、次のようなふるまい(操作)があります。
- 吠える
- 食べる
- 走る
プログラムでは、これらを1つの「Dog」というオブジェクトにまとめて扱うイメージです。
このように「1つのまとまりとして扱いたいもの」をオブジェクト化すると覚えておくと良いです。
C言語風の構造体で「オブジェクトっぽさ」を体験
構造体と関数で「疑似オブジェクト」を作る
オブジェクト指向言語ではクラスが使えますが、ここではイメージしやすいように、C言語のstructと関数を使って「オブジェクトっぽいもの」を作ってみます。
Dog構造体と操作関数の例
#include <stdio.h>
#include <string.h>
/* 犬を表す構造体 (状態をまとめたもの) */
typedef struct {
char name[32]; // 名前
int age; // 年齢
double weight; // 体重
} Dog;
/* 犬を初期化する関数 (コンストラクタ的な役割) */
void initDog(Dog *dog, const char *name, int age, double weight) {
strncpy(dog->name, name, sizeof(dog->name) - 1);
dog->name[sizeof(dog->name) - 1] = '\0'; // 終端
dog->age = age;
dog->weight = weight;
}
/* 犬に吠えさせる関数 (ふるまい) */
void bark(Dog *dog) {
printf("%s がワン!と吠えました。\n", dog->name);
}
/* 犬に食べさせる関数 (ふるまい) */
void eat(Dog *dog, double foodWeight) {
dog->weight += foodWeight * 0.2; // 食べた量の一部が体重に
printf("%s が %.1f kg 食べました。現在の体重は %.1f kg です。\n",
dog->name, foodWeight, dog->weight);
}
/* メイン関数: Dog「オブジェクト」を使ってみる */
int main(void) {
Dog pochi;
Dog shiro;
/* 2匹の犬を初期化 (オブジェクトの生成イメージ) */
initDog(&pochi, "ポチ", 3, 5.0);
initDog(&shiro, "シロ", 2, 4.2);
/* ポチに吠えさせる */
bark(&pochi);
/* シロにごはんを食べさせる */
eat(&shiro, 0.5);
return 0;
}
ポチ がワン!と吠えました。
シロ が 0.5 kg 食べました。現在の体重は 4.3 kg です。
この例では、Dog構造体が「状態」、関数群が「ふるまい」を担当しています。
本格的なオブジェクト指向言語では、これらがクラスの中に一体化して書けるようになります。
継承と多態性を「乗り物」の例で直感的に理解する
継承とは「共通部分をまとめて再利用する」こと

継承とは、共通する性質を1つにまとめ、似た種類のオブジェクトを効率的に作る仕組みです。
例えば、車・自転車・バスはそれぞれ違う乗り物ですが、共通して「移動する」ことができます。
この共通部分を「乗り物(Vehicle)」として定義し、車や自転車がそれを引き継ぐイメージです。
こうすることで
- 共通の機能を1回だけ書けば良い
- 車特有の機能、自転車特有の機能だけを追加で書けば良い
という再利用性の高い設計ができます。
多態性とは「同じ命令で、対象ごとに違う動きをする」こと

多態性(ポリモーフィズム)は、同じ操作でも、オブジェクトの種類によって中身の動きが変わる性質です。
例えば、すべての乗り物にmove()という関数(メソッド)があるとします。
同じmove()でも
- 車なら、エンジンを動かしてタイヤを回す
- 自転車なら、人がペダルをこぐ
- バスなら、乗客の乗り降りも考慮して停留所ごとに停まる
と、実際の動きは違います。
それでも、プログラム側からは単にmove()と呼ぶだけでよい、という状態を作るのが多態性です。
これにより、「詳細な違いを意識せず、共通のインターフェースだけ見てコードを書ける」ようになります。
オブジェクト指向を使うメリットを整理する

ここまでの内容を踏まえて、オブジェクト指向を使うと何が嬉しいのかをまとめます。
1つは見通しのよいコードになることです。
状態とふるまいがオブジェクトとしてまとまることで、「この処理はどこに書けばよいか」「どこを見れば分かるか」がはっきりします。
もう1つは再利用がしやすいことです。
一度作ったクラスを、別のプログラムでもそのまま使えたり、継承で少しだけ機能を付け足したクラスを作ったりできます。
さらに、変更や拡張に強いというメリットもあります。
オブジェクトごとに役割が分かれているため、仕様変更があっても影響範囲を限定しやすく、全体を壊さずに修正できます。
まとめ
オブジェクト指向は、「現実のものごとをオブジェクトとしてモデル化し、状態とふるまいを1つにまとめて扱う考え方」です。
クラスを設計図、オブジェクトを実物と考えると直感的に理解しやすくなります。
カプセル化で中身を隠し、継承で共通部分をまとめ、多態性で共通の操作を柔軟に扱えることで、見通しがよく再利用しやすい設計が可能になります。
まずは身近な「犬」「車」「家電」などを頭に思い浮かべながら、自分ならどうクラスやオブジェクトを設計するかを考えてみると、オブジェクト指向の考え方が一気に身近に感じられるはずです。
