みなさんこんにちは!ひろぽんです!
今回は拡張メソッドでinterfaceのデフォルト実装する方法について書いていきたいと思います。
正直C#8.0からInterfaceのデフォルト実装って標準でできるようになっているのですが、現場の関係でC#8.0使えない人はinterfaceのデフォルト実装をどうすればいいのか?ってなると思います。
今回はそういう人に向けてInterfaceのデフォルト実装を拡張メソッドを用いて実装する方法について書いていきます!
そもそも拡張メソッドとは?
そもそも拡張メソッドとは何ぞや?というはなしなのですが、結論から言うとstaticな静的メソッドをインスタンスメソッドと同じような感じで呼び出せる仕組みです。
例えばintの数字に2乗にした数字を返すというSquareという関数を拡張メソッドとして持たせると下記のようになります。
    public static class IntExtenssionMethod
    {
        public static int Square(this int num)
        {
            return num * num;
        }
    }この関数を実際に使うと下記のようになります。
    class Program
    {
        static void Main(string[] args)
        {
            int num = 2;
            // 2の2乗
            Console.WriteLine(num.Square());
            // 2の3乗
            Console.WriteLine(num.Square().Square());
            // 2の4乗
            Console.WriteLine(num.Square().Square().Square());
            Console.WriteLine();
        }
    }これを実行して。

あたかもint型が初めから持っていた関数のように扱えますよね?
では例をもう一つ。
文字列の前後に***○○***という感じでデコレーションする関数を拡張メソッドとして実装すると下記のようになります。
    public static class StringExtenssionMethod
    {
        public static string Decoration(this string str)
        {
            return $@"***{str}***";
        }
    }これを実行すると!
            string str = "Hello World";
            Console.WriteLine(str.Decoration());
            Console.ReadLine();
このように拡張メソッドとはClassの定義の外で定義しているのにも関わらず、あたかも初めからそのクラスにあったというような感じで振舞えるのです!
これをInterfaceに応用するとデフォルト実装が実現できます!
Interfaceに拡張メソッドを入れるとデフォルト実装できる
ではこの記事の本題であるInterfaceに拡張メソッドでデフォルト実装をする方法について書いていきたいと思います。
まずは下記のようなInterfaceがあります。
namespace InterfaceExtenssionMethod
{
    public interface IAnimal
    {
        string RoarSound { get; }
    }
}このInterfaceは動物を表しており、RoarSoundという動物の鳴き声のプロパティだけを持っています。
そしてRoarという拡張メソッドを用意してこの関数を実行すれば鳴き声を出力するようにします。
    public static class AnimalExtenssionMethod
    {
        public static void Roar(this IAnimal animal)
        {
            Console.WriteLine(animal.RoarSound);
        }
    }そしてIAnimalを継承したDogクラスとCatクラスを実装します。
    public class Dog : IAnimal
    {
        public string RoarSound => "わんわん";
    }
    public class Cat : IAnimal
    {
        public string RoarSound => "にゃーにゃー";
    }するとどうでしょうか。InterfaceにRoarという関数が元から合ったように振舞います。
            var dog = new Dog();
            dog.Roar();
            Console.ReadLine();
違う動物クラスを入れて実行してみたら、その動物クラスが持っている鳴き声で鳴きます。
            var dog = new Dog();
            var cat = new Cat();
            dog.Roar();
            cat.Roar();
            Console.ReadLine();
以上Interfaceに拡張メソッドでデフォルト実装をする方法でした!
今回のサンプルコードはGithubに上げています!
下記リポジトリに「InterfaceExtenssionMethod」というフォルダ名で今回のサンプルコードを上げています!


	
コメント