学習記録

プログラミングの学習中に調べて解決したこと等の記録です。

継承の際のindstance ofの使い方

 

 どのような状況だったのか

ゲーム作成を通し、PHPオブジェクト指向を学習中のこと。

 

 

どのような結果にしたかったかと実際の結果

どのクラスのインスタンスかによって魔法攻撃ができたり、回復魔法が使えたり挙動を変えたかったので、

Monsterクラス(親クラス)

MagicMonsterクラス(子クラス、Monsterクラスを継承)

HealMonsterクラス(子クラス、継承の継承、Monsterクラスから見れば孫?クラス)

とし、

 

 
<?php

if ($_SESSION['monster'] instanceof MagicMonster) {
 
〜MagicMonsterにさせたい行動〜

 } else if($_SESSION['monster'] instanceof HealMonster){
 
〜HealMonsterにさせたい行動〜
 
 } else if($_SESSION['monster'] instanceof Monster){
 
~Monsterにさせたい行動〜
 
 }

?>
 

と最初書いていました。

 

 その結果

 ところが、

「HealMonster が出てきているはずなのに、ifの分岐でMagicMonsterに入ってしまっていて、MagicMonsterの挙動をしている」

 

「MagicMonsterとMonsterが出てきたときはちゃんと正しい分岐に入って、意図した挙動をしている」

 

ということがおき、HealMonsterの時のみ思った通りに動いていないという結果になりました。

 

 

解決策

  if文の順番を、

MagicMonsterクラス(子クラス)

HealMonsterクラス(孫?クラス)

Monsterクラス(親クラス)

 

ではなく

 

HealMonsterクラス(孫?クラス)

MagicMonsterクラス(子クラス)

Monsterクラス(親クラス)

にしたところ、解決。

 

<?php
if ($_SESSION['monster'] instanceof HealMonster) {
 
〜HealMonsterにさせたい行動〜

 } else if($_SESSION['monster'] instanceof MagicMonster{
 
〜MagicMonsterにさせたい行動〜
 
 } else if($_SESSION['monster'] instanceof Monster){
 
~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度で情報が得られなかったときも、繰り返し確認することが必要だと身に染みて感じました。