継承の際のindstance ofの使い方
どのような状況だったのか
どのような結果にしたかったかと実際の結果
どのクラスのインスタンスかによって魔法攻撃ができたり、回復魔法が使えたり挙動を変えたかったので、
Monsterクラス(親クラス)
MagicMonsterクラス(子クラス、Monsterクラスを継承)
HealMonsterクラス(子クラス、継承の継承、Monsterクラスから見れば孫?クラス)
とし、
と最初書いていました。
その結果
ところが、
「HealMonster が出てきているはずなのに、ifの分岐でMagicMonsterに入ってしまっていて、MagicMonsterの挙動をしている」
「MagicMonsterとMonsterが出てきたときはちゃんと正しい分岐に入って、意図した挙動をしている」
ということがおき、HealMonsterの時のみ思った通りに動いていないという結果になりました。
解決策
if文の順番を、
MagicMonsterクラス(子クラス)
↓
HealMonsterクラス(孫?クラス)
↓
Monsterクラス(親クラス)
ではなく
HealMonsterクラス(孫?クラス)
↓
MagicMonsterクラス(子クラス)
↓
Monsterクラス(親クラス)
にしたところ、解決。
なぜそれで解決したのか?
試しにMonsterクラスをif文の先頭に持ってきたところ、MagicMonster が呼ばれているときも、HealMonsterが呼ばれているときも、ifの分岐がMonsterクラスに入っていました。
そのため仮説として
「HealMonsterクラスはMonsterクラスとMagicMonsterクラスを継承していて、その2つの要素も持っているため、instanceof で判定すると、親要素のほうでも反応する」
ということなのではないか、と考えていましたが、PHPマニュアルを見たところ
instanceof は、ある変数が 特定の親クラスを継承したクラスのオブジェクトのインスタンスであるかどうかを調べることもできます。
例2 継承したクラスでの instanceof の使用法
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>上の例の出力は以下となります。
bool(true) bool(true)引用 PHPマニュアルhttps://www.php.net/manual/ja/language.operators.type.php
と記載がありました。
「HealMonster が出てきているはずなのに、ifの分岐でMagicMonsterに入ってしまっていて、MagicMonsterの挙動をしている」
という動きをしていると私が思っていたときのPHP側の実際の動きとしては、
「HealMonsterをinstanceofで調べたら、MagicMonsterを親クラスとして継承したクラスだったので、if ($_SESSION['monster'] instanceof MagicMonster のルートに入っていた」
ということで、挙動自体はおかしくなく、instance ofの使い方をきちんと理解していないことが今回のつまづきの原因でした。
最後に
マニュアルが意図していたことに気付いたのが、解決策を思いついて「結局なんでなだろう?」ともう一度見直したときだったので、1度で情報が得られなかったときも、繰り返し確認することが必要だと身に染みて感じました。