今回は,継承可能なシングルトン,つまり,この抽象クラスを継承すればなんでもシングルトンになれるぜ〜ってクラスを紹介します。
継承ツリーという概念と、みんな大好きジェネリックが出てきます。
誰しも一回は通る道
public abstract class BaseSingleton<T>
{
public static T Instance;
public BaseSingleton()
{
Instance = (T)this;
}
}
public class Singleton : BaseSingleton<Singleton> { }
これじゃコンパイラーは通しちゃくれません。なぜでしょうか。
Cannot convert type 'BaseSingleton<T>' to 'T'.
Instance = (T)this;
のところでひっかっています。これはObject => BaseSingleton<T>
とObject => T
という二つの継承ツリーが存在しており、言語仕様として別ツリーにはキャストできないからです。つまり、T
とBaseSingleton<T>
の関係を教えてやればいいのです。
結論
正解は、これ。
public abstract class BaseSingleton<T> where T : BaseSingleton<T>
{
public static T Instance;
public BaseSingleton()
{
Instance = (T)this;
}
}
public class Singleton : BaseSingleton<Singleton> { }
where
節により、継承関係が明示されました。
継承ツリーはObject => BaseSingleton<T> => T
となっており、これならキャスト可能です。
余談: UnityのMonoBehaviourをシングルトンにしてみる
同じように。
public abstract class SingletonBehaviour<T> : MonoBehaviour where T : SingletonBehaviour<T>
{
public static T instance;
public SingletonBehaviour()
{
instance = (T)this;
}
private protected virtual void OnDestroy()
{
instance = null;
}
}
まとめ
ジェネリックってほんとにムズカシイ!けどめっちゃ楽しい!