インターフェイスとは?
Unity開発でより柔軟で保守性の高いコードを書きたいと思ったことはありませんか?
異なるクラス間で共通の機能を統一的に扱えるようになり、テストしやすく拡張性の高い設計を実現できる——それがインターフェイスの力です。
インターフェイスとは、クラスが持つべき機能を決めるための設計図のようなものです。
実際の処理は持っておらず、インターフェイスを継承したクラスに対して「この機能を必ず実装してね」という約束事を定義します。
一見すると抽象的で難しく感じるかもしれませんが、実はUnity開発における多くの課題を解決してくれる強力な仕組みです。
例えば、プレイヤーキャラクターの入力処理、敵AIの行動パターン、UIの表示切り替えなど、様々な場面でインターフェイスが活躍します。
インターフェイスの役割
1.共通の決まりを定義する
インターフェイスには、クラスや構造体が実装するべきメソッド、プロパティなどを定義します。
継承先ではそれらの機能を実装していないとコンパイルエラーになるので、
継承先では必ずそれらの機能を持っているため、異なるクラス間で共通の機能を統一的に扱えるようになります。
動物を例に、以下のインターフェイスを定義しました。
鳴く機能を持たせるためメソッドがあります。
public interface IAnimal
{
// 鳴く
void MakeSound();
}
IAnimal
を継承したクラスを定義する場合は、MakeSound
メソッドを必ず実装する必要があります。
public class Dog : IAnimal
{
public void MakeSound()
{
Debug.Log("ワン");
}
}
public class Cat : IAnimal
{
public void MakeSound()
{
Debug.Log("ニャーン");
}
}
2.多態性を実現する
インターフェイスを使うことで、異なる型のオブジェクトを共通のインターフェイス型で扱うことができます。
これによって、より柔軟で拡張性が高いコード設計が可能になります。
前段の例で、IAnimal
を継承した動物のクラスをいくつかあるとします。
それらはIAnimal
を継承しているので、IAnimal
型のコレクションにまとめることができます。
var dog = new Dog();
var cat = new Cat();
var bird = new Bird();
var sheep = new Sheep();
IList<IAnimal> animals = new()
{
dog,
cat,
bird,
sheep
};
foreach(var animal in animals)
{
// 動物毎に鳴き声を再生
animal.MakeSound();
}
3.疎結合な設計を可能にする
クラス間の依存関係を具体的なクラスではなくインターフェイスにすることで、疎結合な設計ができます。
これによりテストのしやすさや再利用性が高まり、メンテナンスしやすいコードになります。
以下にゲームコントローラの入力を表現する簡易のインターフェイスを用意しました。
IGamePad
インターフェイスを継承した、
実際の入力を返すGamePad
と
ランダムで入力を返すRandomInput
を用意しました。
public interface IGamePad
{
bool IsButtonDown();
}
public class GamePad : IGamePad
{
public bool IsButtonDown()
{
return /* ゲームパッドのボタンの状態を返す */;
}
}
public class RandomInput : IGamePad
{
public bool IsButtonDown()
{
return random(0, 100) < 50; // 半分の確率でボタンを押したことにする
}
}
以下のPlayer
クラスのコンストラクタには、IGamePad
インターフェイスを継承しているクラスを渡すことができます。
public class Player
{
private readonly IGamePad _gamePad;
public Player(IGamePad gamePad)
{
_gamePad = gamePad;
}
public void Update()
{
if(_gamePad.IsButtonDown())
{
// ジャンプさせる
}
}
}
通常時はGamePad
クラスを渡しゲームコントーラの入力に応じて動作させられます。
所謂ガチャ押しの状態を表現してテストしたい場合にRandomInput
をクラスを渡してランダムな操作をすることもできます。
この際Player
クラスは特に変更の必要もありません。
これ以外に過去の入力情報を保存しておいて再現させる、といったことも実現できそうです。
まとめ
インターフェイスは慣れないと一見難しく感じるかもしれませんが、
「共通のルールを決めて、いろいろなクラスを同じように使えるようにする仕組み」と考えると分かりやすいんじゃないでしょうか。
沢山の似たような機能を量産する場合、同じインターフェイスを継承しておくことで機能を共通化できます。
今回のような簡単なサンプルコードではあまり伝わらないかもしれませんが、
是非ご自身のプロジェクトにも取り入れてみてください。
📣おしらせ!
Unity Asset StoreでICONIC ESSENTIALS SALEが開催中です。 日替わりでお得なアセットが登場します。