リファクタリングの頭の体操のような話です。
基底クラスのループ処理の中で、特定のクラスでのメソッドを呼ぶ時の実装について、思ったのでメモ。
以下のコードは、
- 抽象クラスのSpriteを用意
- HumanとMagicianはSpriteクラスを継承して、実装
- Magicianの時だけは魔法使いなので、Magicメソッドを実装
- Human,Human,Magicianという配列をループさせて、その中で、Magicianの時にだけMagicメソッドを呼び出したい
といったコードです。
using System; public class Program { public abstract class Sprite { public void Act() { } } public class Human:Sprite { } public class Magician:Sprite { public void Magic() { Console.WriteLine("Fire!"); } } public static void Main() { var party = new Sprite[] { new Human(), new Human(), new Magician() }; foreach (var sprite in party) { sprite.Act(); if (sprite is Magician magician) { magician.Magic(); } } } }
ゲームだと、このようなコードを私を書くことが多かったです。
ただ、こういう時は
using System; public class Program { public abstract class Sprite { public void Act() { } } public class Human:Sprite { } public class Magician:Sprite { // privateに出来る!!! private void Magic() { Console.WriteLine("Fire!"); } public static void Magic(Sprite sprite) { if (sprite is Magician magician) { magician.Magic(); } } } public static void Main() { var party = new Sprite[] { new Human(), new Human(), new Magician() }; foreach (var sprite in party) { sprite.Act(); Magician.Magic(sprite); } } }
と、Magicのクラスメソッドはprivateにして静的メソッドで呼べた方がいいですね。
もっと複雑になったら、基底クラスに新たなメソッドを作るとか、delegateを経由して呼び出されるようにするとか、考えることになるでしょう。d
どこまで頑張るかはケースバイケースですね。