Minxin
Pyhonにおいて、多重継承に問題がいろいろあるため、
継承によるクラスの拡張を簡単にできるやり方がある
基底クラス
class Character():
def __init__(self, HP, MP, power=0, skill=None) -> None:
self.HP = HP
self.MP = MP
self.power = power
self.skill = skill if skill is not None else {}
Mixinクラス
class CharacterMixin:
def normal_attack(self, name):
print(f'{name}が攻撃しました。')
print(f'敵に{self.power}のダメージを与えました')
def show_attack_power(self):
print(f"攻撃力は{self.power}")
def show_skill(self):
print(f"持っている職業スキルは{self.skill}")
def show_status(self):
print(f'HP:{self.HP} MP:{self.MP} 攻撃力:{self.power} スキル:{self.skill}')
class MagicMixin:
def io_attack(self, name):
if self.skill.get("イオ", 0):
print(f'{name}がイオを唱えました。')
def mera_attack(self, name):
if self.skill.get("メラ", 0):
print(f'{name}がメラを唱えました。')
class WarriorMixin:
def defence(self, name):
print(f'{name}が敵の攻撃を受け流しました。')
def charge(self, name):
print(f'{name}が「ためる」を使いました。')
職業クラス
class Wizard(Character, CharacterMixin, MagicMixin):
pass
class Warrior(Character, CharacterMixin, WarriorMixin):
pass
Playerクラス
class Player():
def __init__(self, name, job) -> None:
self.job = job
self.name = name
実行
if __name__ == "__main__":
# 職業クラス
wizard = Wizard(HP=30, MP=30, power=10, skill={"メラ": 1, "イオ": 1})
warrior = Warrior(HP=50, MP=0, power= 30, skill={"受け流し" : 1,"ためる": 1})
# Playerクラス
marin = Player(name="マリン", job=wizard)
tuyoshi = Player(name='ツヨシ', job=warrior)
# 名前の表示
print("Player Name:", marin.name)
# ステータスの表示
marin.job.show_status()
# できる攻撃
marin.job.normal_attack(marin.name)
marin.job.io_attack(marin.name)
marin.job.mera_attack(marin.name)
print('-------')
tuyoshi.job.show_status()
tuyoshi.job.normal_attack(tuyoshi.name)
tuyoshi.job.defence(tuyoshi.name)
実行結果
Player Name: マリン
HP:30 MP:30 攻撃力:10 スキル:{'メラ': 1, 'イオ': 1}
マリンが攻撃しました。
敵に10のダメージを与えました
マリンがイオを唱えました。
マリンがメラを唱えました。
-------
HP:50 MP:0 攻撃力:30 スキル:{'受け流し': 1, 'ためる': 1}
ツヨシが攻撃しました。
敵に30のダメージを与えました
ツヨシが敵の攻撃を受け流しました。
感想
Mixinで多重継承ができて、拡張しやすいと感じています。
通常の多重継承だと順番を気にする必要があるが、
Mixinの場合、基底クラス、共通メソッドクラス、カスタムクラスという順番を決めておけば、
それなりに使えるかと思います。
但し、4,5以上はお勧めしません。
事例で示してるのは、職業クラスからPlayerクラスに至って、継承をやめており、
職業をPlayerクラスのプロパティにし、
jobクラスが持っているメソッドを活用して、実行するようにしている。
なお、拡張する場合は、メソッドを増やすことができ、
攻撃相手(enemyなどクラス)を引数として、引き渡せば、それなりに拡張できると思います。
2025/08/17:
職業クラスはPassでも動きましたので、クラスの継承宣言すると、Characterクラス、CharacterMixinクラス、職業Mixinクラスすべて関連づけされる仕組みのようです。
以上。
ご参考:
WizardとWarriorクラスが動作する理由
多重継承によって、各MixinのメソッドやCharacterの属性がインスタンスに統合されるためです。
- WizardはCharacter(HP, MP, power, skillなどの属性)、CharacterMixin(攻撃やステータス表示)、MagicMixin(魔法攻撃)のすべてのメソッド・属性を継承します
- WarriorはCharacter(属性)、CharacterMixin(攻撃やステータス表示)、WarriorMixin(防御やためる)のすべてのメソッド・属性を継承します
- Pythonの多重継承では、インスタンス生成時にCharacterの__init__が呼ばれ、Mixinのメソッドも使えるようになります
- そのため、WizardやWarriorのインスタンスは、各Mixinのメソッドを問題なく呼び出せます。