オブジェクト指向練習用のPythonコードを書いてみる


## はじめに

本記事は[HUITアドベントカレンダー2018](https://qiita.com/advent-calendar/2018/huit)の4日目になります。

## この記事について

今回は「オブジェクト指向の書き方はわかったけど、実際どういう風に活用すればいいの？」という方向けに、オブジェクト指向を活用した簡単なシミュレーションゲーム的なものをPythonで書いてみたいと思います。

テーマは「某大学生の一日」です。~~一体誰得なんだ~~

なお、プログラム全体がつたないのはご容赦ください。なにしろ僕自身がプログラミング歴1年未満のひよっこなので…

## まずは見てほしい

```OneDay.py
# ここからプレイヤー
class Person:
    def __init__(self, building):
        self.building = building    # 現在地
        print(f"{self.building.name}にいる")

    def move(self, building):
        self.building = building    # 現在地の更新
        print(f"{self.building.name}に移動した")
    
    def eat(self):
        print(f"{self.building.serve()}を食べた")
    
    def study(self):
        if self.building.has_teacher:
            print(f"{self.building.teach()}を勉強した")

    def sleep(self):
        if self.building.has_bed:
            print("もう夜だ\nおやすみ")

# ここから建物
class Home:
    has_bed = True

    def __init__(self):
        self.name = "マイホーム"

class KyoyoTo:
    has_teacher = True

    def __init__(self):
        self.name = "教養棟"
    
    def teach(self):
        return input("受けたい授業名を入力してください：")

class Restaurant:
    def __init__(self):
        self.name = ""
        self.menu = ""
    
    def serve(self):
        return self.menu

class HokuShoku(Restaurant):
    def __init__(self):
        self.name = "北部食堂"
        self.menu = "ビュッフェ"

class Chuo(Restaurant):
    def __init__(self):
        self.name = "中央食堂"
        self.menu = "スープカレー"

# ここからメインの処理
def main(player):
    count = 0
    while count < 3:
        player_move(player)
        if player.building.name == "教養棟":
            player.study()
        else:
            player.eat()
        count += 1
    player.move(Home())
    player.sleep()
    
def player_move(player):
    option = [None , KyoyoTo(), HokuShoku(), Chuo()]
    while True:
        key = input("どこに移動しますか？　1.{0[1].name} 2.{0[2].name} 3.{0[3].name}：".format(option))
        try:
            player.move(option[int(key)])
            break
        except:
            print("有効な入力ではありません！")

if __name__ == '__main__':
    ore = Person(Home())
    main(ore)
```

実際に動かすとこんな感じです。

```
マイホームにいる
どこに移動しますか？　1.教養棟 2.北部食堂 3.中央食堂：3
中央食堂に移動した
スープカレーを食べた
どこに移動しますか？　1.教養棟 2.北部食堂 3.中央食堂：1
教養棟に移動した
受けたい授業名を入力してください：日本国憲法
日本国憲法を勉強した
どこに移動しますか？　1.教養棟 2.北部食堂 3.中央食堂：2
北部食堂に移動した
ビュッフェを食べた
マイホームに移動した
もう夜だ
おやすみ
```

## プログラムの解説

たぶんしないと思います。

## プログラムの特徴

- プログラム全体を「プレイヤー」「建物」「メイン処理」という風に分けてみました。**プログラムの一部分をオブジェクトとして切り出すことで、全体の見通しが良くなります。**
- オブジェクト同士がデータを受け渡す様子を意識して書きました。**プログラミングは結局はデータのやり取りである**ことが実感できたと思います。
- 上記に加えて、`Object.method()`という書き方ができるので、**「主語」と「動詞」というイメージ**を持ってコードを組むことができました。
- `Restaurant`クラスを継承して各種食堂クラスを定義したので、**親クラスで定義した`serve`メソッドを子メソッドでも使うことができます。**
- `input`を使う関係上、簡易的な例外処理（`try-except`を書いただけ）を行いました。

## おわりに

このプログラムはもともと僕自身がPythonを勉強するために作ったものです。
クオリティはどうであれ**自分で想像したことを表現することで、なりよりプログラミングへの実感が湧きますし、モチベーションアップにも繋がりました。**
一見意味のないように見えるプログラムでも、**一度自分で作ってみる**のが良いと思います。そこで使った技術をほかで応用できることも少なくありません。

また、Pythonでオブジェクト指向を学ぶのはどうかという意見もあるとは思いますが、ひとまずの練習なので…
そもそもPythonはどのライブラリを使って何を行うかに重点が置かれるので、**標準の文法についてあまり時間をかけるべきではない**かもしれません。
ただ、まだ扱える言語の少ない現状では、**きっちり理解している言語から書き方を広げていく**のも悪くはないのかなと考えています。

まあPythonでオブジェクト指向を学ぶことの一番の問題は、データ型を明示することができないことですかね…

次は何かコンパイラ言語にも挑戦していきたいと思います。