IronPythonを使った多重継承

C#の場合、多重継承はインタフェースを使うことになりますが、実装クラスへの委譲を書くのがちょっと面倒です。一方、Pythonは実装の多重継承ができるのでこれを利用して委譲の手書きを手抜きできないか試してみました。

まずは、多重継承させるインタフェースを用意します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IronPythonSampleLib
{
    public interface IBasicCalc
    {
        double Add(double x, double y);
        double Sub(double x, double y);
    }

    public interface IAdvanceCalc
    {
        double Mul(double x, double y);
        double Div(double x, double y);
    }
}

このインタフェースの実装をPythonで行って、さらに多重継承したクラスも用意します。

import clr
clr.AddReference('IronPythonSampleLib')
from IronPythonSampleLib import *

class BasicCalc(IBasicCalc):
	def Add(self, x, y):
		return x + y

	def Sub(self, x, y):
		return x - y

class AdvanceCalc(IAdvanceCalc):
	def Mul(self, x, y):
		return x * y

	def Div(self, x, y):
		return x / y

class Calc(BasicCalc, AdvanceCalc, IBasicCalc, IAdvanceCalc):
	pass

最後に、これをC#から呼び出します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IronPython.Hosting;
using IronPythonSampleLib;


namespace IronPythonSample
{
    class Program
    {
        static void TestBasic(IBasicCalc calc)
        {
            Console.WriteLine(calc.Add(10, 20));
            Console.WriteLine(calc.Sub(10, 20));
        }

        static void TestAdvance(IAdvanceCalc calc)
        {
            Console.WriteLine(calc.Mul(10, 20));
            Console.WriteLine(calc.Div(10, 20));
        }

        static void Main(string[] args)
        {
            var ip = Python.CreateRuntime();
            // IronPythonのクラス定義はscopeから取得する必要がある
            var scope = ip.ExecuteFile("Calc.py");

            // Calcは多重継承したクラス
            var calcClass = scope.GetVariable("Calc");
            dynamic calc = ip.Operations.CreateInstance(calcClass);

            // IBasicCalcとして呼び出す
            TestBasic(calc);
            // IAdvanceCalcとして呼び出す
            TestAdvance(calc);
        }
    }
}

/* 結果
30
-10
200
0.5
 */

うまく使えば言語の弱点を補完し合えそうですね。過去にやったネタな気がしますが、その時はdynamcがなかったし改良版ということで。(^^;