#クラス継承
名前の通り,基底クラスの機能を持った派生クラスを作ります.
*途中で力尽きたので多分加筆します
#一つのクラスの継承
ここは,単純に,Creatureクラスを元に,Warrior, Magicianクラスを作ってます.
初期levelに応じて,能力を上昇させています.
status(self)関数では,パラメータの列挙を行っています.(テスト用)
__init__
はインスタンス生成の際に実行されます.
Worrior, Magicianクラスでは,武器をもたせたり,職業名の変更を行っています.
class Creature(object):
def __init__(self, level=1, weapon=None):
self.level = level
self.hp = 0
self.mp = 0
self.attack = 0
self.defence = 0
self.weapon = weapon
self.job = "neet"
def status(self):
return "Job:{} | HP:{} | MP:{} | Atk:{} | Def:{} | Weapon:{}".format \
(self.job, self.hp, self.mp, self.attack, self.defence, self.weapon)
class Warrior(Creature):
def __init__(self, level):
super().__init__(level)
self.attack += 3 * level
if self.weapon is None:
self.weapon = "sword"
if self.job == "neet":
self.job = "Warrior"
else: self.job += "Warrior"
class Magician(Creature):
def __init__(self, level):
super().__init__(level)
self.mp += 4 * level
if self.weapon is None:
self.weapon = "rod"
if self.job == "neet":
self.job = "Magic"
else: self.job += "Magic"
下のようにlevelに応じて能力の上昇,基底クラスのstatus関数が使えています.
>>> print(Warrior(5).status())
Job:Warrior | HP:0 | MP:0 | Atk:15 | Def:0 | Weapon:sword
>>> print(Magician(5).status())
Job:Magic | HP:0 | MP:20 | Atk:0 | Def:0 | Weapon:rod
#複数クラス継承
複数クラスの場合も先ほどとやることはほとんど同じです.
class MagicWarrior(Warrior, Magician):
def __init__(self, level):
super().__init__(level)
class WarriorMagic(Magician, Warrior):
def __init__(self, level):
super().__init__(level)
ここで,注意する点は,下の出力でわかるように,
super()を用いた時__init__
が呼ばれる順番が後ろからになります.
この順番は,mro()で確認ができます.
>>> print(MagicWarrior(5).status())
Job:MagicWarrior | HP:0 | MP:20 | Atk:15 | Def:0 | Weapon:rod
>>> print(WarriorMagic(5).status())
Job:WarriorMagic | HP:0 | MP:20 | Atk:15 | Def:0 | Weapon:sword
>>>
>>> WarriorMagic.mro()
[<class 'class_test.WarriorMagic'>, <class 'class_test.Magician'>, <class 'class_test.Warrior'>, <class 'class_test.Creature'>, <class 'object'>]
#superを使わないとどうなるか,
例えば,
class WarriorMagic(Magician, Warrior):
def __init__(self, level):
# super().__init__(level)
Warrior.__init__(self, level)
Magician.__init__(self, level)
一見,同じように見えるのですが,initの呼び出しの回数が違います.
この場合,Warrior > Creature, Magician > Warrior > Creature
といった感じで呼び出しています.
superを使った場合では,Magician > Warrior > Creature
と呼び出し回数が違います.
Job:WarriorMagic | HP:0 | MP:20 | Atk:15 | Def:0 | Weapon:sword
##さらに,基底クラスのWarriorとMagicianクラスもsuperを使わずに定義すると
class Warrior(Creature):
def __init__(self, level):
# super().__init__(level)
Creature.__init__(self, level)
self.attack += 3 * level
if self.weapon is None:
self.weapon = "sword"
if self.job == "neet":
self.job = "Warrior"
else: self.job += "Warrior"
class Magician(Creature):
def __init__(self, level):
# super().__init__(level)
Creature.__init__(self, level)
self.mp += 4 * level
if self.weapon is None:
self.weapon = "rod"
if self.job == "neet":
self.job = "Magic"
else: self.job += "Magic"
Job:Magic | HP:0 | MP:20 | Atk:0 | Def:0 | Weapon:rod
こうすると,せっかく最初のWarriorで能力とかをつけたのに,
Magicianで2回目のinitを呼び出したせいで,パラメタが初期化され,ただのMagicianの能力しか割り振られていません.
その結果,下のようになってしまいます.
流れ的には,
Warrior > Creature, Magician > Creature
のような感じで呼び出されていて,見てわかる通りCreatureを2回呼び出されていて,先ほどとは違い,2回目にWarriorが呼び出されていないので,Worriorのinitが反映されない形になってしまってます.
#まとめ
とりあえず,継承する際はsuperを基本的に使う
superを使った際に呼び出されるのは後ろから