【Python OOP入門】ToDoアプリをクラスで改造!オブジェクト指向の考え方
公開日: 2025年10月13日
前回の記事では、「関数」を使ってToDoアプリのコードを整理し、各機能の役割を明確にしました。 しかし、もしこのアプリがもっと複雑になり、「タスクに優先度を付けたい」「締め切り日を設定したい」といった機能を追加したくなったらどうでしょう? todos というただのリストと、バラバラに定義された関数だけでは、だんだんと管理が難しくなってきます。
そこで登場するのが、Pythonをはじめとする現代的なプログラミング言語の根幹をなす考え方、「オブジェクト指向プログラミング(OOP)」と、そのための設計図である「クラス(class)」です。
難しそうに聞こえるかもしれませんが、心配はいりません。 この記事では、おなじみのToDoアプリを「クラス」を使って改造する過程を通して、オブジェクト指向がなぜこれほどまでに強力で、世界中のエンジニアに愛されているのかを、分かりやすく解説します。
🚗 クラスとは? オブジェクトとは?
非常に簡単に言うと、クラスとは「モノの設計図」です。 例えば、「自動車」というクラス(設計図)には、「色」「速度」といったデータ(属性)と、「走る」「止まる」といった機能(メソッド)が定義されています。
そして、その設計図を元に作られた実体が「オブジェクト」**です。 「赤いフェラーリ」や「青いプリウス」は、どちらも「自動車」クラスから作られた、それぞれが独立したオブジェクトなのです。
💡 なぜクラスを使うのか?
関連するデータと機能を一つの「モノ」としてまとめる(これをカプセル化と言います)ことで、コードの整理がしやすくなり、まるでレゴブロックを組み合わせるように、直感的にプログラムを組み立てられるようになります。
🛠️ ToDoアプリをクラスベースにリファクタリング
それでは、この考え方をToDoアプリに応用してみましょう。 今回は2つのクラスを作ります。
- Taskクラス:一つ一つのタスクを表現するための設計図。
- TodoListクラス:タスクのリスト全体を管理するための設計図。
1. Taskクラスの設計
まず、個々のタスクが持つべきデータ(属性)を考えます。今回はシンプルに「タスクの内容(文字列)」だけを持たせましょう。
class Task:
def __init__(self, content):
self.content = content
def __str__(self):
return self.content
- class Task:: これで`Task`という名前のクラスの設計を開始します。
- def __init__(self, content):: これはコンストラクタと呼ばれる特殊なメソッドです。Taskオブジェクトが作られる(インスタンス化される)時に、最初に一度だけ呼ばれます。
- self.content = content: 受け取ったcontent(タスク内容)を、そのオブジェクト自身のデータ(属性)として保存しています。selfはそのオブジェクト自身を指す特別な変数です。
- def __str__(self):: このメソッドを定義しておくと、print(task_object)のようにオブジェクトを直接プリントしようとした時に、ここで返した文字列(この場合はタスクの内容)が綺麗に表示されます。
2. TodoListクラスの設計
次に、Taskオブジェクトのリストを管理するためのクラスを作ります。以前、関数としてバラバラに定義していた機能を、このクラスのメソッドとしてまとめ上げます。
import json
FILENAME = "todos.json"
class TodoList:
def __init__(self):
self.tasks = self.load_todos()
def load_todos(self):
try:
with open(FILENAME, "r", encoding="utf-8") as f:
# JSONから読み込んだただの文字列を、Taskオブジェクトに変換する
contents = json.load(f)
return [Task(content) for content in contents]
except FileNotFoundError:
return []
def save_todos(self):
with open(FILENAME, "w", encoding="utf-8") as f:
# Taskオブジェクトのリストを、ただの文字列のリストに変換して保存
contents = [task.content for task in self.tasks]
json.dump(contents, f, ensure_ascii=False, indent=2)
def add_task(self):
content = input("追加するタスクを入力してください: ")
task = Task(content) # 新しいTaskオブジェクトを作成
self.tasks.append(task)
self.save_todos()
print("タスクを追加しました。")
def list_tasks(self):
print("--- ToDoリスト ---")
for i, task in enumerate(self.tasks, start=1):
print(f"{i}: {task}") # __str__メソッドが呼ばれる
print("------------------")
def complete_task(self):
# 以前の関数とロジックはほぼ同じ
# ... (詳細は最終コードを参照)
3. メイン処理の劇的な変化
クラスの設計が完了すると、メインの`while`ループは驚くほどシンプルで直感的になります。
# --- メイン処理 ---
def main():
todo_list = TodoList() # TodoListオブジェクトを一つ作成
print("オブジェクト指向ToDoリストアプリ")
while True:
command = input("コマンドを選択してください (add, list, done, exit): ")
if command == "add":
todo_list.add_task()
elif command == "list":
todo_list.list_tasks()
elif command == "done":
todo_list.complete_task()
elif command == "exit":
print("アプリを終了します。")
break
else:
print("無効なコマンドです。")
if __name__ == "__main__":
main()
todo_list.add_task() のように、「ToDoリスト(オブジェクト)に、タスクを追加する(メソッドを呼び出す)」という、「主語.動詞()」の形で、まるで自然言語のようにコードが読めるようになりました。これこそがオブジェクト指向の力です!
まとめ
今回は、ToDoアプリを「クラス」ベースにリファクタリングすることで、オブジェクト指向プログラミングの第一歩を踏み出しました。
- class で、データとそれを操作する機能をまとめた「設計図」を作る。
- 設計図から オブジェクト という「実体」を作り、操作する。
- これにより、コードが部品化され、直感的で、拡張しやすい構造になる。
オブジェクト指向をマスターすることは、単にPythonの文法を覚えることとは次元の違う、ソフトウェア全体の「設計思想」を学ぶことです。 この考え方を身につければ、どんなに大規模で複雑なアプリケーションにも、自信を持って立ち向かえるようになります。
プログラミング学習に必須ツール!
記事で紹介したコードがよく分からなかったり、ご自身のコードについてもっと知りたい場合は、AIコード解説ツールが便利です。コードを貼り付けるだけで、AIが日本語で分かりやすく解説します。
AIコード解説ツールを使ってみる →