車から学ぶ!オブジェクト指向の考え方!【#JavaScript】

車から学ぶ!オブジェクト指向の考え方!【#JavaScript】

福田です!
今回はプログラミングをするうえで、いやというほど出てくるオブジェクト指向について解説していきます!
自分は学生時代、主にJavaを触っていたのですが学習する中でよくこの言葉をよく聞きました。

「Javaはオブジェクト指向言語だから」

??オブジェクト指向??
もちろん気になって調べるのですが、何度調べてもまぁわからない事だらけでした。
もちろん、自分の調べ方の問題ももちろんあったと思うのですが、専門用語だらけなのもよくないことだと思います…!

そこで今回はコードを書かない人でもわかるようにできる限りたとえ話で“オブジェクト指向”について説明しようと思います!
それではよろしくお願いします!
もちろん、たとえ話だけでわかった気になるだけの可能性もあるので、意識したコードを実際に書いてみるのも大事ですよ!

オブジェクト指向とは?

オブジェクト指向とは、ある物体のデータと動きを丸っとひとまとまりにした”オブジェクト”を組み合わせていこうね!
というものになります!

早速のたとえ話ですが、車があるとします。

車にはナンバープレートや車種、色など様々な特徴がありますね。
これがオブジェクトのデータ、属性(プロパティ)にあたります。

また、アクセルを踏むと前に進む、ハンドルを傾けると曲がる、ブレーキを踏むと停止するなどの動作がありますね。
これがオブジェクトの動き、処理(メソッド)となります。

オブジェクト指向の基本概念

では、オブジェクト指向の基本的な概念を、引き続き車の例で見ていきましょう!

カプセル化

カプセル化とは、オブジェクトの中身を外部から直接触れないように包み込むことです。

例えば、車のエンジンを考えてみましょう。運転手はアクセルを踏むだけで車が走り出しますが、エンジンの中で何が起きているかを知らなくても運転できますよね?

これがカプセル化です。複雑な内部の仕組みを隠して、シンプルな操作方法(インターフェース)だけを提供することで、使う人は内部構造を気にせず利用できるようになります。

JavaScriptで表すと:

const car = {
  // プロパティ(データ)
  speed: 0,
  engineRunning: false,
  
  // メソッド(動き)
  startEngine() {
    this.engineRunning = true;
    console.log("エンジンがかかりました!");
  },
  
  accelerate() {
    if (this.engineRunning) {
      this.speed += 10;
      console.log(`速度: ${this.speed}km/h`);
    } else {
      console.log("先にエンジンをかけてください!");
    }
  }
};

// 使い方
car.startEngine(); // エンジンをかける
car.accelerate();  // アクセルを踏む

継承

継承とは、すでにあるオブジェクトの特徴や機能を引き継いで、新しいオブジェクトを作ることです。

例えば「車」という大きな概念があって、その中に「スポーツカー」や「トラック」などがありますよね。スポーツカーやトラックは車の基本的な機能(走る、止まる、曲がる)を持ちつつ、それぞれ独自の特徴も持っています。

スポーツカーは加速が速い、トラックは荷物がたくさん積めるなど、それぞれ特化した能力を持っています。でも基本は「車」なんです!

JavaScriptでの例:

// 基本の車クラス
class Vehicle {
  constructor(color) {
    this.color = color;
    this.speed = 0;
  }
  
  drive() {
    this.speed += 10;
    console.log(`${this.color}の車が走り出しました!速度: ${this.speed}km/h`);
  }
  
  brake() {
    this.speed = 0;
    console.log("車が停止しました");
  }
}

// 車を継承したスポーツカークラス
class SportsCar extends Vehicle {
  constructor(color) {
    super(color); // 親クラスのコンストラクタを呼び出す
  }
  
  // オーバーライド:親クラスのメソッドを上書き
  drive() {
    this.speed += 30; // スポーツカーだから加速が速い!
    console.log(`${this.color}のスポーツカーが猛スピードで走り出しました!速度: ${this.speed}km/h`);
  }
  
  // 独自のメソッド
  turboBoost() {
    this.speed += 50;
    console.log(`ターボ発動!速度: ${this.speed}km/h`);
  }
}

// 使い方
const normalCar = new Vehicle("青");
normalCar.drive(); // 青の車が走り出しました!速度: 10km/h

const ferrari = new SportsCar("赤");
ferrari.drive(); // 赤のスポーツカーが猛スピードで走り出しました!速度: 30km/h
ferrari.turboBoost(); // ターボ発動!速度: 80km/h

ポリモーフィズム(多態性)

ポリモーフィズムとは、同じ命令でも対象によって違う動きをすることです。

例えば「運転する」という行為は、車でも自転車でもオートバイでも可能ですが、それぞれ操作方法が違いますよね。けれど、どれも「運転する」という言葉で表現できます。

これがポリモーフィズムです。異なるオブジェクトに対して同じメソッド名を使えるので、コードがシンプルになります。

// 乗り物インターフェース(JavaScriptでは概念的なもの)
class Vehicle {
  drive() {
    // 継承先でオーバーライドされることを期待
    console.log("乗り物が動きます");
  }
}

class Car extends Vehicle {
  drive() {
    console.log("車がエンジンを始動させて走り出します");
  }
}

class Bicycle extends Vehicle {
  drive() {
    console.log("自転車がペダルをこいで前に進みます");
  }
}

class Motorcycle extends Vehicle {
  drive() {
    console.log("バイクがエンジンを吹かして走り出します");
  }
}

// ポリモーフィズムの利用例
function startJourney(vehicle) {
  // どんな乗り物でも同じdriveメソッドを呼べる
  vehicle.drive();
}

startJourney(new Car()); // 車がエンジンを始動させて走り出します
startJourney(new Bicycle()); // 自転車がペダルをこいで前に進みます
startJourney(new Motorcycle()); // バイクがエンジンを吹かして走り出します

実生活で考えるオブジェクト指向

他にも例を挙げてみましょう!

スマホアプリの例

お気に入りの料理アプリがあるとしましょう。このアプリには「レシピ」というオブジェクトがたくさんあります。

レシピオブジェクトのプロパティ(属性):

  • 料理名
  • 調理時間
  • 材料リスト
  • 難易度

レシピオブジェクトのメソッド(動作):

  • お気に入りに追加する
  • レシピを共有する
  • 材料を2人前/4人前に変換する

これらのレシピオブジェクトを集めて、アプリという大きなプログラムができています。

ゲームの例

RPGゲームを考えてみましょう。キャラクターたちはそれぞれオブジェクトです。

キャラクターオブジェクトのプロパティ:

  • 名前
  • HP(体力)
  • MP(魔力)
  • 攻撃力
  • 防御力

キャラクターオブジェクトのメソッド:

  • 攻撃する
  • 防御する
  • アイテムを使う
  • 魔法を使う

さらに、「戦士」「魔法使い」「盗賊」など、キャラクタークラスを継承したサブクラスがあって、それぞれ異なる特殊能力を持っています(継承とポリモーフィズム)。

JavaScriptでのオブジェクト指向実装

実際のJavaScriptコードで、オブジェクト指向がどう表現されるか見てみましょう!

オブジェクトリテラル

最もシンプルなオブジェクトの作り方です:

const dog = {
  // プロパティ
  name: "ポチ",
  breed: "柴犬",
  age: 3,
  
  // メソッド
  bark() {
    console.log("ワンワン!");
  },
  
  eat(food) {
    console.log(`${this.name}は${food}を食べています`);
  }
};

dog.bark(); // ワンワン!
dog.eat("ドッグフード"); // ポチはドッグフードを食べています

クラス構文(ES6以降)

複数の同じような種類のオブジェクトを作るときは、クラスを使うと便利です:

class Animal {
  constructor(name, species) {
    this.name = name;
    this.species = species;
    this.hungry = true;
  }
  
  eat() {
    this.hungry = false;
    console.log(`${this.name}はご飯を食べました!満腹です`);
  }
  
  speak() {
    console.log("何か鳴きます");
  }
}

// 継承の例
class Dog extends Animal {
  constructor(name, breed) {
    super(name, "犬"); // 親クラスのコンストラクタを呼び出す
    this.breed = breed;
  }
  
  // オーバーライド
  speak() {
    console.log("ワンワン!");
  }
  
  // 独自メソッド
  fetch() {
    console.log(`${this.name}はボールを取ってきました!`);
  }
}

// 使い方
const pochi = new Dog("ポチ", "柴犬");
pochi.eat(); // ポチはご飯を食べました!満腹です
pochi.speak(); // ワンワン!
pochi.fetch(); // ポチはボールを取ってきました!

オブジェクト指向のメリット

オブジェクト指向でプログラミングすると、どんないいことがあるのでしょうか?

  1. コードの再利用性が高まる:一度作ったクラスは何度でも使い回せます。新しい車種が必要になったら、基本の「車」クラスを継承するだけでOK!

  2. 保守性が高まる:例えば、すべての車の加速方法を変更したい場合、親クラスの「車」のメソッドだけを変更すれば、すべての車に変更が適用されます。

  3. 現実世界のモデル化がしやすい:人間が物事を考える方法に近いので、プログラムの設計がわかりやすくなります。

  4. チーム開発がスムーズ:大きなプログラムでも、オブジェクトごとに分担して開発できます。

まとめ

オブジェクト指向とは、データ(プロパティ)と動作(メソッド)をひとまとめにしたオブジェクトを組み合わせてプログラムを作る考え方です。

主要な概念は:

  • カプセル化:内部構造を隠して、シンプルな操作方法を提供する
  • 継承:既存のクラスの特徴を引き継いで新しいクラスを作る
  • ポリモーフィズム:同じメソッド名でも、オブジェクトによって異なる動作ができる

JavaScriptでは、オブジェクトリテラルやクラス構文を使ってオブジェクト指向プログラミングができます。

最初は難しく感じるかもしれませんが、実際にコードを書きながら少しずつ理解していきましょう!オブジェクト指向の考え方をマスターすれば、より大きく、メンテナンスしやすいプログラムが書けるようになりますよ。

それでは、素敵なオブジェクト指向ライフを!
福田でした!


現在
株式会社チョモランマ
株式会社シェルパ
3Dmodeljapan株式会社
ではスタッフを大募集しております!!
Unreal Engine4、AI、プログラミングや建築パースに興味がある方!
ぜひご応募下さい!!
初心者の方、未経験の方やインターンを受けてみたい方々でも大歓迎です!!