オブジェクト指向開発について #1

# 最初に

私自身まだまだ、オブジェクト指向についてわかった気になっているので、アウトプットがてらメモに残しました。
下記書籍は、オブジェクト指向については勿論のこと、実際にJavaでコードが記載されており、ハンズオン形式で学べるので、初学者、私のようにエンジニア経験が浅い人にはオススメの書籍かなと思います。

【読んだ書籍】
[なぜ、あなたはJavaでオブジェクト指向開発ができないのか](https://www.amazon.co.jp/%E3%81%AA%E3%81%9C-%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AFJava%E3%81%A7%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E9%96%8B%E7%99%BA%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B-Java%E3%81%AE%E5%A3%81%E3%82%92%E5%85%8B%E6%9C%8D%E3%81%99%E3%82%8B%E5%AE%9F%E8%B7%B5%E3%83%88%E3%83%AC%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-%E3%82%A2%E3%82%AF%E3%83%AD%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/477412222X/ref=sr_1_1?crid=KHP4OFR7JTKB&keywords=%E3%81%AA%E3%81%9C+%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AFjava%E3%81%A7%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E9%96%8B%E7%99%BA%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B&qid=1683432461&s=instant-video&sprefix=%E3%81%AA%E3%81%9C%E3%80%81%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AFJava%2Cinstant-video%2C427&sr=1-1)

※あくまで、自分の中で大事だと思った部分だけメモしている形になります。
## Lesson1. オブジェクト指向をなぜ難しいと思うのか

### **プログラミングの3つのステップ**

プログラムで開発するのはソフトウェアだが、さまざまなものがある。その中でも共通することは、**現実世界で行うことをコンピュータに肩代わりさせるためのもである**、ということ。

プログラミングの流れ

1. コンピュータに行わせたいことを理解する
2. 理解したことを説明できるレベルまで整理する
3. コンピュータにわかる言葉へ翻訳する

### プログラミングできない理由

1. 入門書などに掲載されているプログラムを読んで、理解はできるが、自分で作れず、何から手をつければいいのかわからない状態
    
    ⇨ 人の書いた説明を読んで理解はできる。でも、**自分で説明できない**状態（Step1、2を飛ばした状態）
    
2. プログラミングを勉強して、数十行程度のプログラムは書けるが、それより大きいものになると、中々上手く作ることができない状態
    1. 説明できるレベルまで落とし込めていない
    2. そもそも翻訳する力が足りていない

### なぜオブジェクト指向で開発できないのか

下記理由が挙げられている

- オブジェクト指向言語の文法のみの理解に留まっている
- クラスや継承の概念を知っているだけ

## Lesson2. オブジェクト指向は本当に必要なのか

### コンピュータにジャンケンさせる

まずは、オブジェクト指向なしで

1. **コンピュータに行わせたいことを理解する**
    1. 2人のプレイヤーがジャンケンを行う様子を、コンピュータ上で再現
    2. ジャンケンは3回勝負
    3. 引き分けの場合も1回の勝負とする
    4. 3回勝負後の勝ち数が同じ場合は引き分けとする
    
2. **理解したことを説明できるレベルまで整理する**

```
1. ジャンケン開始の合図
2. プレイヤー1が何を出すのか決める
3. プレイヤー2が何を出すのか決める
4. どちらの勝ちかを判定して、結果を表示
5. 勝ったプレイヤーの勝ち数に1を加える
6. 勝負回数に1を加える
7. 勝負回数が3回に満たなければ、２に戻る
8. 勝者を判定して、結果を表示
```

3. **コンピュータがわかる言語に翻訳する**

```
public class SimpleJanken {
    // ジャンケンの手を表す定数
    public static final int STONE = 0; // グー
    public static final int SCISSORS = 1; //チョキ
    public static final int PAPER = 2; //パー

    public static void main(String[] args) {
        // 1. ジャンケン開始
        System.out.println("【ジャンケン開始】");
        // ランダムで出す手を表示させる
        double randomNum = 0;

        // プレイヤー1、プレイヤー2の勝ち数
        int player1WinCount = 0;
        int player2WinCount = 0;

        // 6. 勝負回数に1を加える
        // 7. 勝負回数が3回に満たなければ、２に戻る
        for (int i = 0; i < 3; i++) {
            System.out.println("【" + (i + 1) + "回戦目】");
            // 2．プレイヤー1が何を出すのか決める
            int player1Hand = 0;

            // 0以上3未満の少数として乱数を得る
            randomNum = Math.random() * 3;
            if (randomNum < 1) {
                player1Hand = STONE;
                System.out.print("グー");
            } else if (randomNum < 2) {
                player1Hand = SCISSORS;
                System.out.print("チョキ");
            } else if (randomNum < 3) {
                player1Hand = PAPER;
                System.out.print("パー");
            }

            System.out.print(" vs. ");

            // 3．プレイヤー2が何を出すのか決める
            int player2Hand = 0;

            // 0以上3未満の少数として乱数を得る
            randomNum = Math.random() * 3;
            if (randomNum < 1) {
                player2Hand = STONE;
                System.out.println("グー");
            } else if (randomNum < 2) {
                player2Hand = SCISSORS;
                System.out.println("チョキ");
            } else if (randomNum < 3) {
                player2Hand = PAPER;
                System.out.println("パー");
            }

            // 4.どちらの勝ちかを判定して、結果を表示
            if ((player1Hand == STONE && player2Hand == SCISSORS)
                    || (player1Hand == SCISSORS && player2Hand == PAPER)
                    || (player1Hand == PAPER && player2Hand == STONE)) {
                // 5. プレイヤー1が勝った回数を数える
                player1WinCount++;
                System.out.println(" プレイヤー1が勝ちました! ");
            }
            // プレイヤー2の勝った回数を加算する
            else if ((player2Hand == STONE && player1Hand == SCISSORS)
                    || (player2Hand == SCISSORS && player1Hand == PAPER)
                    || (player2Hand == PAPER && player1Hand == STONE)) {
                // 5. プレイヤー1が勝った回数を数える
                player2WinCount++;
                System.out.println(" プレイヤー2が勝ちました! ");
            } else {
                System.out.println(" 引き分けです! ");
            }
        }

        // 8. 勝者を判定して、結果を表示
        System.out.println("【ジャンケン終了】");
        if (player1WinCount > player2WinCount) {
            System.out.println(player1WinCount + "対" + player2WinCount + "でプレイヤー1の勝ちです！ ");
        } else if (player1WinCount < player2WinCount) {
            System.out.println(player2WinCount + "対" + player1WinCount + "でプレイヤー1の勝ちです！ ");
        } else {
            System.out.println(player2WinCount + "対" + player1WinCount + "で引き分けです！");
        }
    }
}
```

## ジャンケンプログラムを拡張する

上記のプログラムの場合下記の問題が起こる

- プレイヤーごとに名前を変える
- プレイヤーの人数が増えた時
- プレイヤーの手の出し方を、全てランダムではなくてプレイヤーごとに変える etc..

⇨これらは、オブジェクト指向で解決することができる。

次章からは、上記プログラムをオブジェクト指向を用いて改変していく