ベースクラスから派生クラスにキャストしようとしたときに、はまってしまったことをまとめておきます。
処理内容
メンバー変数を1つ保持しているベースクラス(CastBase.cs)と
1つ変数を追加した派生クラス(CastA.cs)を用意しました。
using UnityEngine;
/// <summary>
/// ベースクラス
/// </summary>
public class CastBase
{
/// <summary>
/// ベースクラスのメンバー変数
/// </summary>
public int BaseMemberNum;
}
/// <summary>
/// 派生クラス
/// </summary>
public class CastA : CastBase
{
public int AMemberNum;
}
2つのクラスを使って、以下のような処理しました。(Unity上で動かしています。)
実行はTestMethod内のキャストで失敗し、null参照でエラーを吐いてしまいます。
using UnityEngine;
/// <summary>
/// メインクラス
/// </summary>
public class Main : MonoBehaviour
{
void Start()
{
var castBase = new CastBase(); //ベースクラスでインスタンス化
var castA = new CastBase();//ベースクラスでインスタンス化
TestMethod(castBase, castA);
}
//ベースクラスを引数として受け渡すメソッド
void TestMethod(CastBase castBase, CastBase castA)
{
Debug.Log(castBase.BaseMemberNum);
var castedA = castA as CastA; //キャスト失敗。castedAにはnullが返ってきます。
Debug.Log(castedA.BaseMemberNum); //null参照でエラー
Debug.Log(castedA.AMemberNum);
}
}
修正方法はcastAをインスタンス化するときにベースクラスではなく、
CastA型でインスタンス化する必要があります。
CastA型で宣言をし、あらかじめCastAの領域を確保しないとキャストに失敗してしまうようです。
using UnityEngine;
/// <summary>
/// メインクラス
/// </summary>
public class Main : MonoBehaviour
{
void Start()
{
var castBase = new CastBase(); //ベースクラスでインスタンス化
var castA = new CastA(); // CastA型でインスタンス化する
TestMethod(castBase, castA);
}
void TestMethod(CastBase castBase, CastBase castA)
{
Debug.Log(castBase.BaseMemberNum);
var castedA = castA as CastA;
Debug.Log(castedA.BaseMemberNum);
Debug.Log(castedA.AMemberNum);
}
}
同じクラスに書かれると、なんてこともない問題ですが、実際に直面したのは、宣言とキャストする場所が離れてしまっていて、なかなか原因を発見することができませんでした。