【デザインパターン with Python】1-5. Classを使ってみよう: 継承とオーバーライド

記事タイトルとURLをコピーする

はじめに

こんにちは。孔子の80代目子孫兼アプリケーションサービス部の孔です。今回はデザインパターンを学ぶ上で絶対必要となるClassの特性についてみてみます。

今回紹介するのは「継承」と「オーバーライド」になります。

Classの継承をしてみよう

継承とは、既存のClassを引き継いで再利用することを指します。プログラムを作っていくと、似たようなことをやるClassがいっぱいできることがあります。その例として、今回はRPGゲームを作るプログラムで、戦士・野蛮人・弓使いというクラス(ややこしいですが、RPGで職業の意味で使われるクラスです!)を作ってみようと思います。

# 戦士クラス
class Warrior:
    def __init__(self):
        self.attack_point = 20
        self.speed = 30
        self.dexterity = 10
        self.weapon = ""
 
    def attack(self):
        return self.attack_point
 
    def equipment(self, weapon_type):
        if weapon_type != "sword":
            print("その武器は使用できません")
            return None
 
# 野蛮人クラス
class Barbarian:
    def __init__(self):
        self.attack_point = 50
        self.speed = 10
        self.dexterity = 0
        self.weapon = ""
 
    def attack(self):
        return self.attack_point
 
    def equipment(self, weapon_type):
        if weapon_type != "sword":
            print("その武器は使用できません")
            return None
 
    def roar(self):
        self.attack_point += 50
        self.dexterity -= 50
 
# 弓使いクラス
class Archer:
    def __init__(self):
        self.attack_point = 10
        self.speed = 40
        self.dexterity = 50
        self.weapon = ""
 
    def attack(self):
        return self.attack_point
 
    def equipment(self, weapon_type):
        if weapon_type != "bow":
            print("その武器は使用できません")
            return None
 
    def power_of_nature(self):
        self.attack_point += 10
        self.speed += 10
        self.dexterity += 10

この三つのクラスですが、みんな共通してattackメソッドを持っていて、やっていることは全く同じです。これだと同じ処理を何回も書いているので、コードの変更が発生したときに全てのクラスに対して処理を変更しないといけないので、とても大変そうです。このように、共通して発生するようなメソッドを共通化するために、継承を使います。

継承とは、既存のClassを引き継いで再利用することを指すとのことでしたね。継承元を「親クラス」といい、継承先を「子クラス」と言います。子クラスでは、親クラスが持っている全ての処理を引き継ぐことができます。そのため、共通するこのattackという処理は以下のように親クラスに書いてしまえば、それぞれのクラスではattackメソッドを実装しなくてもよくなります。

# 親クラス
class Class:
    # 同じ処理は親クラスに持たせて、子クラスに継承させる!
    def attack(self):
        return self.attack_point
 
# 戦士クラス
class Warrior(Class):
    def __init__(self):
        self.attack_point = 20
        self.speed = 30
        self.dexterity = 10
        self.weapon = ""
 
    def equipment(self, weapon_type):
        if weapon_type != "sword":
            print("その武器は使用できません")
            return None
 
# 野蛮人クラス
class Barbarian(Class):
    def __init__(self):
        self.attack_point = 50
        self.speed = 10
        self.dexterity = 0
        self.weapon = ""
 
    def equipment(self, weapon_type):
        if weapon_type != "sword":
            print("その武器は使用できません")
            return None
 
    def roar(self):
        self.attack_point += 50
        self.dexterity -= 50
 
# 弓使いクラス
class Archer(Class):
    def __init__(self):
        self.attack_point = 10
        self.speed = 40
        self.dexterity = 50
        self.weapon = ""
 
    def equipment(self, weapon_type):
        if weapon_type != "bow":
            print("その武器は使用できません")
            return None
 
    def power_of_nature(self):
        self.attack_point += 10
        self.speed += 10
        self.dexterity += 10

オーバーライド

継承ができたら、次はオーバーラーライドになります。オーバーライドとは、親クラスが持っているメソッドを上書き(オーバーライド)することを指します。先ほどの処理のequipmentメソッドを見てみましょう。戦士と野蛮人は剣を使いますが、弓使いは弓を使います。これだと、弓使いだけ特殊なことをやっているので、全てのクラスがequipmentを持つよりは、弓使いだけ特殊なロジックを使うようにした方が楽ですね。つまり、デフォルトでは剣は装備可能で、弓使いだけ弓以外の武器を使えないように上書きする、にしたらよさそうです。

# 親クラス
class Class:
    def attack(self):
        return self.attack_point
 
    # デフォルトでは、このクラスを継承するクラスは剣を装備できる
    def equipment(self, weapon_type):
        if weapon_type != "sword":
            print("その武器は使用できません")
            return None
 
# 戦士クラス
class Warrior(Class):
    def __init__(self):
        self.attack_point = 20
        self.speed = 30
        self.dexterity = 10
        self.weapon = ""
 
# 野蛮人クラス
class Barbarian(Class):
    def __init__(self):
        self.attack_point = 50
        self.speed = 10
        self.dexterity = 0
        self.weapon = ""
 
    def roar(self):
        self.attack_point += 50
        self.dexterity -= 50
 
# 弓使いクラス
class Archer(Class):
    def __init__(self):
        self.attack_point = 10
        self.speed = 40
        self.dexterity = 50
        self.weapon = ""
 
    # 継承元のメソッド名と同様のメソッド名を定義することで、オーバーライドすることができます!
    def equipment(self, weapon_type):
        if weapon_type != "bow":
            print("その武器は使用できません")
            return None
 
    def power_of_nature(self):
        self.attack_point += 10
        self.speed += 10
        self.dexterity += 10

コードがだいぶ簡潔でスッキリしていて、クラス間の共通処理と個別処理がどれなのかが分かりやすくなりましたね!

最後に

次回は「抽象Classとは何か」です。今回紹介した継承とオーバーライドが密接に関わりますので、今回の内容をしっかり理解して次の記事を読むとより得られるものが多いかと思います!またよろしくお願いしますー!

シリーズ一覧

孔 允培 (執筆記事の一覧)

アプリケーションサービス部 ディベロップメントサービス課

孔子の80代目子孫