はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#,Unity】dynamicを使ってダックタイピングを実装してみる

はじめに

今回はダックタインピングを実装してみようという記事になります。

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は一般的に遅く、静的言語の良さも失われます。

静的言語に慣れきっている私からしたら言葉は悪いですが気持ち悪くて仕方ないですね。

使わなくても良い場面ならば、使わないに越したことはないでしょう。

ではまた。