{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[]},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["# クラスについて\n","メインの講義はここまでで終了となります。最後におまけの講義として、クラスという機能についてごく簡単にご紹介します。\n","\n","やや中級者以上向けの内容となりますが、これからPythonの学習を続けていただくうえで重要となります。Pythonを始めたばかりの方ですと今は難しくて理解できないかもしれませんが、今後クラスという言葉を目にしたときは、この講義資料で復習してみてください。\n"],"metadata":{"id":"X-0eVhgpXWD5"}},{"cell_type":"markdown","source":["## クラスとインスタンス\n","クラスについて学ぶと、「**クラス**」と「**インスタンス**」という言葉が必ず登場します。クラスは製品の設計図、インスタンスは設計図を元に生産された製品、と例えられることが多いです。\n","\n","\n","クラスの説明はどうしても難しくなってしまうため、データ構造化よりもシンプルで分かりやすい例で考えてみます。\n","\n","例えば、「車」クラスという設計図あって、その設計図をもとに「田中さんの赤い乗用車」インスタンスや、「鈴木さんの白いトラック」インスタンスという具体的な製品が作られます。これらは持ち主、色、モデルこそ違いますが、「ドアを開ける」「走る」といった共通の機能を持っています。\n","\n","実際のソースコードを見てみましょう。"],"metadata":{"id":"0hXsQosq5GoJ"}},{"cell_type":"code","source":["class Car:\n"," def __init__(self, owner, color, model):\n"," self.owner = owner\n"," self.color = color\n"," self.model = model\n","\n"," def open(self):\n"," print(f\"{self.owner}さんの{self.color}の{self.model}のドアが開いた!\")\n","\n"," def run(self):\n"," print(f\"{self.owner}さんの{self.color}の{self.model}が走った!\")\n","\n","red_car = Car(\"田中\", \"赤\", \"乗用車\")\n","red_car.open()\n","red_car.run()\n","\n","print(\"-\"*50)\n","\n","white_car = Car(\"鈴木\", \"白\", \"トラック\")\n","white_car.open()\n","white_car.run()"],"metadata":{"id":"FU7EAoGAUmTb"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["持ち主、色、モデルが違っても、車クラスのインスタンスにすれば「初期化する」「ドアを開ける」「走る」といった機能が共通化されるので、プログラムの理解・作成がとてもやりやすくなります。\n","\n","なお、このopenやrunは関数の形をしていますが、クラスの中で定義されたものは「**メソッド**」と呼びます。\n","\n","メソッドは、「Pythonの基礎2」の講義でもご紹介しました。そこでは次のとおり構文をご説明しましたが、この「対象のデータ」はまさにクラスのことだったのです。\n","\n","~~~\n","対象のデータ.メソッド名(引数)\n","~~~\n","\n","また、ドアを開ける機能を修正したいときに、openメソッドを変更すれば全ての車のインスタンスに変更が適用されるので、乗用車は修正されたけど、トラックは修正されなかった!といった修正ミスが少なくなります。"],"metadata":{"id":"ZTDN8r4UUxbw"}},{"cell_type":"markdown","source":["## 継承とオーバーライド\n","車だけでなく、同じ「乗り物」である「飛行機」も考えてみましょう。\n","\n","「持ち主」「色」「モデル」という属性は、車であっても飛行機であっても必要な情報です。「ドアを開ける」という機能も共通でしょう。\n","\n","一方、車は「走る」ですが、飛行機は「飛ぶ」という機能の方が適切です。\n","\n","このようなとき、「乗り物」というクラスを作って「持ち主」「色」「モデル」という属性や、「ドアを開ける」という機能を定義します。また、「走る」「飛ぶ」を抽象的に表す「動く」という機能を定義しておきます。\n","\n","この「乗り物」を継承して「車」「飛行機」というクラスを作り、「動く」が呼ばれたときには、車クラスであれば「走る」、飛行機クラスであれば「飛ぶ」ようにしてあげることができます。これには、メソッドのオーバーライドと呼ばれる機能を使います。\n","\n","実際のソースコードを見てみましょう。"],"metadata":{"id":"pDpa1RT_VdyH"}},{"cell_type":"code","source":["class Machine:\n"," def __init__(self, owner, color, model):\n"," self.owner = owner\n"," self.color = color\n"," self.model = model\n","\n"," def open(self):\n"," print(f\"{self.owner}さんの{self.color}の{self.model}のドアが開いた!\")\n","\n"," def move(self):\n"," # 「走る」「飛ぶ」など様々な乗り物が動く機能を抽象化する\n"," print(f\"{self.owner}さんの{self.color}の{self.model}が動いた!\")\n","\n","class Car(Machine):\n"," def move(self):\n"," # Machineクラスのmoveを上書きして「走る」にする\n"," print(f\"{self.owner}さんの{self.color}の{self.model}が走った!\")\n","\n","class Airplane(Machine):\n"," def move(self):\n"," # Machineクラスのmoveを上書きして「飛ぶ」にする\n"," print(f\"{self.owner}さんの{self.color}の{self.model}が飛んだ!\")\n","\n","red_car = Car(\"田中\", \"赤\", \"乗用車\")\n","red_car.open()\n","red_car.move()\n","\n","print(\"-\"*50)\n","\n","blue_airplane = Airplane(\"佐藤\", \"青\", \"ヘリ\")\n","blue_airplane.open()\n","blue_airplane.move()"],"metadata":{"id":"wmOMtJvhXIvA"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["このように、抽象的なクラスから具体的なクラスへと継承することで、「車」「飛行機」という異なる種類の乗り物であっても、共通の属性や操作は統合して一か所に定義することができます。"],"metadata":{"id":"lD6OmnR_X4Zr"}},{"cell_type":"markdown","source":["## まとめ\n","クラスの特徴・メリットは、「カプセル化」など他にもあります。\n","\n","これらの特徴を生かせる使い方であれば、クラスの活用も検討してみてください。\n","\n","ただし、クラスは最適な使いどころの見極めが非常に難しい機能でもあります。十分に特徴を理解したうえで、乱用はせずに、ここぞという場面で使っていただければと思います。"],"metadata":{"id":"muPnbkVdYVB1"}}]}