【6日でできるPython入門】クラス②


Pythonのクラスは「データ」と「機能(メソッド)」をまとめて管理するための仕組みです。
 「クラス①」ではクラスの基本(定義・属性・メソッド)を学びましたが、実際のプログラミングでは「継承」という仕組みが重要な役割を持ちます。
 継承を使うと、既存のクラスをもとに新しいクラスを作成し、「共通部分の再利用」や「個別の拡張」が簡単にできるようになります。
ここでは、クラスの継承・オーバーライド・super()の使い方をしっかり身につけましょう。

1.継承の基本

1.1. クラスの継承とサブクラスの作成

継承を使うと、親クラスの属性やメソッドを子クラスでそのまま使うことができます。

ファイル名: lesson21-1.py

class Character:
    def __init__(self, name):
        self.name = name
        self.hp = 100
        self.power = 80

    def attack(self, target):
        print(f"{self.name}は{target.name}に攻撃した!")
        target.hp -= self.power
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を倒した!")

class Knight(Character):
    pass

taro = Knight("タロウ")
jiro = Character("ジロウ")
taro.attack(jiro)

実行結果

タロウはジロウに攻撃した!

解説

  • Knight(Character):Characterを継承しています。
  • Knightにはメソッドを定義していませんが、親クラスのものが使えます。
  • 継承元(親クラス)を「スーパークラス」、継承先(子クラス)を「サブクラス」と呼びます。

1.2. オーバーライド(上書き)

子クラスで親クラスのメソッドを上書き(オーバーライド)できます。

ファイル名: lesson21-2.py

class Character:
    def __init__(self, name):
        self.name = name
        self.hp = 100
        self.power = 80

    def attack(self, target):
        print(f"{self.name}は{target.name}に攻撃した!")
        target.hp -= self.power
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を倒した!")

class Knight(Character):
    pass

class Mage(Character):
    def attack(self, target):
        print(f"{self.name}は{target.name}に魔法をかけた!")
        target.hp -= self.power * 2
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を魔法で倒した!")

sakura = Mage("サクラ")
jiro = Character("ジロウ")
sakura.attack(jiro)

実行結果

サクラはジロウに魔法をかけた!
サクラはジロウを魔法で倒した!

解説

  • サブクラスMageattackメソッドを独自に定義しています。
  • 同名メソッドがあれば、親クラスよりも子クラスのメソッドが優先されます

2.super()で親クラスのメソッドを呼ぶ

2.1. super()の基本

子クラスのメソッド内でsuper()を使うと、親クラスの同名メソッドを呼び出せます。

ファイル名: lesson21-3.py

class Character:
    def __init__(self, name):
        self.name = name
        self.hp = 100
        self.power = 80

    def attack(self, target):
        print(f"{self.name}は{target.name}に攻撃した!")
        target.hp -= self.power
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を倒した!")

class Knight(Character):
    pass

class Mage(Character):
    def attack(self, target):
        print(f"{self.name}は{target.name}に魔法をかけた!")
        target.hp -= self.power * 2
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を魔法で倒した!")

class Healer(Character):
    def __init__(self, name):
        super().__init__(name)
        self.mp = 50

    def attack(self, target):
        print(f"{self.name}は{target.name}に光の矢を放った!")
        super().attack(target)

    def heal(self):
        print(f"{self.name}は自分自身を回復した!")
        self.hp += 30

healer = Healer("ミドリ")
enemy = Character("オーガ")
healer.attack(enemy)
healer.heal()
print(f"{healer.name}の現在HP: {healer.hp}")

実行結果

ミドリはオーガに光の矢を放った!
ミドリはオーガに攻撃した!
ミドリは自分自身を回復した!
ミドリの現在HP: 130

解説

  • super().__init__(name)で親の初期化メソッドを呼びます。
  • super().attack(target)で親の攻撃メソッドを追加で呼び出しています。

2.2. 共通部分の集約と拡張

複数のクラスで共通部分を親クラスにまとめ、個別の違いは子クラスで記述すると、
プログラムがすっきり整理できます。

ファイル名: lesson21-4.py

class Character:
    def __init__(self, name):
        self.name = name
        self.hp = 100
        self.power = 80

    def attack(self, target):
        print(f"{self.name}は{target.name}に攻撃した!")
        target.hp -= self.power
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を倒した!")

class Knight(Character):
    pass

class Mage(Character):
    def attack(self, target):
        print(f"{self.name}は{target.name}に魔法をかけた!")
        target.hp -= self.power * 2
        if target.hp <= 0:
            print(f"{self.name}は{target.name}を魔法で倒した!")

class Healer(Character):
    def __init__(self, name):
        super().__init__(name)
        self.mp = 50

    def attack(self, target):
        print(f"{self.name}は{target.name}に光の矢を放った!")
        super().attack(target)

    def heal(self):
        print(f"{self.name}は自分自身を回復した!")
        self.hp += 30

class Monster(Character):
    def __init__(self, name):
        super().__init__(name)
        self.hp = 200
        self.power = 60

    def attack(self, target):
        print(f"{self.name}は{target.name}にかみついた!")
        super().attack(target)

goblin = Monster("ゴブリン")
hero = Knight("ヒーロー")
goblin.attack(hero)

実行結果

ゴブリンはヒーローにかみついた!
ゴブリンはヒーローに攻撃した!

3.クラス継承とオーバーライドのまとめ表

用語意味・ポイント
継承既存クラスの機能を子クラスで再利用class 子(親): ...
オーバーライド子クラスで親クラスと同名のメソッドを上書きするdef attack(self, ...): ...
super()子クラスから親クラスのメソッドを呼び出すsuper().attack(target)
サブクラス継承で作られた新しいクラス(子クラス)Mage, Knight, Monsterなど
スーパークラス継承元のもとになるクラス(親クラス)Character

ここでは、「継承」「オーバーライド」「super()」を使ったクラスの再利用・拡張テクニックを学びました。
次は、より発展的なクラス設計や、クラス同士の関係性について解説していきます。