野球部にカプセル化を説明したい

2023/08/09に公開

おはようございます!
今日も引き続きオブジェクト指向プログラミングについての記事です!

https://zenn.dev/yoojiyang/articles/8cef7446cbe33f

https://zenn.dev/yoojiyang/articles/a56f17713e274e

今日は「カプセル化」について、野球部の皆さんに説明していきたいと思います!

カプセル化とは、オブジェクト指向プログラミングの概念で、クラスの内部データを外部から隠蔽し、特定のメソッドを通じてのみアクセス可能にする手法です。これにより、データの整合性が保たれ、コードの保守が容易になります。

と言われても、よく分からないので今日も野球的に考えていきましょう!

パリーグのチームをクラス化してみる

まず、昨日の復習も兼ねて、パリーグの各チームをプログラムで表現してみましょう。
以下のコードは、パリーグのチームをクラスとして定義し、勝ち数と負け数を管理するものです。

// パリーグクラスを作成 
class PacificLeagueTeam {  
  constructor(teamName) {  // コンストラクタを使ってプロパティを初期化する
    this.teamName = teamName;  // チーム名
    this.wins = 0;  // 勝ち数(初期値は0)
    this.losses = 0;  //負け数初期値は0)
  }
  // winメソッドを定義(勝ち数を増やす)
  win() {
    this.wins += 1;
  }
  // loseメソッドを定義(負け数を増やす)
  lose() {
    this.losses += 1;
  }
}

// 各チームのインスタンスを作成
const Hawks = new PacificLeagueTeam('ホークス');
const Fighters = new PacificLeagueTeam('ファイターズ');
const Marines = new PacificLeagueTeam('マリーンズ');
const Buffaloes = new PacificLeagueTeam('バファローズ');
const Lions = new PacificLeagueTeam('ライオンズ');
const Eagles = new PacificLeagueTeam('イーグルス');

// 例: ホークスが勝利
Hawks.win();
// 例: ファイターズが敗北
Fighters.lose();

// 現状を確認すると、
console.log(Hawks); // PacificLeagueTeam {teamName: 'ホークス', wins: 1, losses: 0}
console.log(Fighters); // PacificLeagueTeam {teamName: 'ファイターズ', wins: 0, losses: 1}

まずクラスは設計図のようなもので、通常のオブジェクトと同じくプロパティとメソッドから構成されているものでした。
さらに、コンストラクタというメソッドを使うことで、生成したインスタンスのプロパティを初期化することが出来ます。
そして、その設計図から生成されたオブジェクトがインスタンスでしたね。インスタンスはクラスのプロパティとメソッドを引き継ぎます。

なんとなく覚えていましたか?これを踏まえると上のコードの内容がわかると思います。
このコードでは、各チームが勝ったり負けたりするたびに、勝ち数と負け数が更新されます。

ここまでが昨日の復習です。

ここから今日のテーマである「カプセル化」について説明していきます。

カプセル化がない場合の問題点

カプセル化を知るために、まずはカプセル化が無いとどう困るのかという事を説明します。

上のコードはカプセル化がされていないことが原因である問題が発生しています。

それは外部から直接勝ち数や負け数を操作できてしまうということです。
例えば、Fighters.wins = 100;とコードを書けば、勝手に勝敗を書き換えることができてしまいます。
シーズン終盤に勝敗表をいじられてはペナントレースがぐちゃぐちゃになってしまいますよね。

Fighters.wins = 100;

console.log(Fighters); //PacificLeagueTeam {teamName: 'ファイターズ', wins: 100, losses: 1}

カプセル化を利用して解決

これを防ぐために「カプセル化」が役に立ちます。以下のようにコードを書き換えることで、カプセル化を実現して勝ち数と負け数を外から書き換えられないようにできます。

ここではカプセル化を実現するために「ゲッターメソッド」というメソッドを使います。
ゲッターメソッドを使うことによって、情報を見ることはできるが、変更することはできないという状態を作れます。

class PacificLeagueTeam {
  //_をつけることで、プライベート変数である事を示す。
  constructor(teamName) {
    this._teamName = teamName;
    this._wins = 0;
    this._losses = 0;
  }

  // ここからゲッターメソッド 
  get teamName() {
    return this._teamName;
  }

  get wins() {
    return this._wins;
  }

  get losses() {
    return this._losses;
  }

  win() {
    this._wins += 1;
  }

  lose() {
    this._losses += 1;
  }
}

// 通常メソッドの動きはそのまま
Fighters.win(); // ファイターズの勝ち数が1増える
Fighters.lose(); // ファイターズの負け数が1増える

// ゲッターメソッド → 読むことはできる
Fighters.wins; // 1
Fighters.lose; // 1

// ゲッターメソッド → 変更はできない
Fighters.wins = 100; // 何も起こらない
Fighters.wins; // 1のまま

このようにすることで、外部から_wins_lossesに直接アクセスすることはできなくなり、勝ち数と負け数は、winメソッドとloseメソッドを通じてのみ変更できるようになります。
これによって、「ある朝起きたら、借金が帳消しどころか、マジックが3になっていた」なんてことが起こらないようにできます。

まとめ

今日のテーマである「カプセル化」について、野球のチームを例に取りながら解説しました。以下、要点を3つにまとめます。

1. データの保護と整合性の確保

カプセル化は、クラスの内部データを外部から直接操作できないようにする概念です。これにより、データの保護と整合性が確保され、不正な操作からデータを守ることができます。

2. ゲッターメソッドの利用

カプセル化を実現するためには、ゲッターメソッドを使用します。これにより、データを読み取ることはできますが、外部から直接変更することはできなくなります。

3. コードの保守性と安全性の向上

カプセル化により、データの安全性が高まり、コードの保守が容易になります。外部からの不正な操作を防ぐことで、バグの発生を減らし、プログラム全体の安定性を向上させることができます。

野球のルールが試合を公正に進めるように、カプセル化もプログラムの「ルール」を守る重要な役割を果たします。プログラミングの世界でも、ルールを守ることが、健全で効率的なシステムを構築する基盤となります。
今日は自分の理解が浅いためか、わかりづらかったかも知れません、、
セッターメソッドの説明も出来ていないので、明日もう一度書いてみたいと思います、、!

最後に、この記事が役立ったと感じた方は、いいねやフォローをお願いします!

それでは今日も学習をスタートします!

Discussion