はじめに
今回はダックタインピングを実装してみようという記事になります。
C#では普通クラスやインターフェイスの型情報によりメソッドを呼び出しますが、「同じ名前のメソッドを持っていれば変数の型は問わない」というダックタイピングという考え方も稀にあります。
最近見かけた例だと、Awaitableパターンですね。
これはGetAwaiter
という名前・引数を持つメソッドを定義すればasync/await
できるようになります。
class MyAwatable { public Awaiter GetAwaiter() { } }
ただC#のような静的言語ではあまり見かけないダックタイピングですが、JavaScriptといった動的言語ではよくあるそうです。
ただしC#でも.NET 4.0より導入されたdynamic
キーワードを用いればできるそうなので、やってみたいと思います。
dynamic
dynamic
キーワードを使うことで、動的型付け変数を定義できます。
よくvar
と混同されますが型宣言を暗黙にしているのではなく、実行時に決まるところが違います。
以下の例をみてみると分かりやすいかもしれません。
using UnityEngine; public class TestBlog : MonoBehaviour { private void Start() { var a = 1; // int型 dynamic b = 1; // dynamic型 dynamic c = 0.1; // dynamic型 dynamic d = "hello"; // dynamic型 b = "hello"; c = " world"; d = 35; dynamic e = b + c + d; Debug.Log(e); // hello world35 } }
普通に実装してみる
まずはインターフェイスを使った方法で例を書いてみます。
using UnityEngine; public class TestBlog : MonoBehaviour { private void Start() { MonsterAttack(new Slime()); MonsterAttack(new Drakee()); } private void MonsterAttack(IMonster monster) { monster.Attack(); } } interface IMonster { public void Attack(); } public class Slime : IMonster { public void Attack() { Debug.Log("スライムの攻撃"); } } public class Drakee : IMonster { public void Attack() { Debug.Log("ドラキーの攻撃"); } }
ダックタイピングで実装する
これをダックタイピングで書き直してみるとこんな感じ。
using UnityEngine; public class TestBlog : MonoBehaviour { private void Start() { MonsterAttack(new Slime()); MonsterAttack(new Drakee()); } private void MonsterAttack(dynamic monster) { monster.Attack(); } } public class Slime { public void Attack() { Debug.Log("スライムの攻撃"); } } public class Drakee { public void Attack() { Debug.Log("ドラキーの攻撃"); } }
このように実際にAttackメソッド
があるかどうかは分かりませんが、そういった名前のメソッドがあること前提に実行をします。
なのでもしAttackメソッド
がなければ実行時にエラーということになります。
さいごに
ただdynamic
は一般的に遅く、静的言語の良さも失われます。
静的言語に慣れきっている私からしたら言葉は悪いですが気持ち悪くて仕方ないですね。
使わなくても良い場面ならば、使わないに越したことはないでしょう。
ではまた。