NOTE: この記事は、当初、ココログの「いげ太のブログ」で公開していたものです。
以下のすばらしい記事を眺めながら。
- C#3.0でMix-in(みたいなの)ができる件 - Programmable Life
- laugh out loudly 拡張メソッドは難しそう
- C#2.0でMix-inを実現する - 開発思考実験日記
これはマネしたい。
Mix-in ってなにさ
イコール多重継承でしょ、と思ってたらちょっと違うようで、また、複数インターフェースの実装を指すのでもないようだ(囚人さんの記事が参考になる)。さりとて、duck typing や structural subtyping の話かというと、それはむしろ論点がズレている。混乱してきた。Wikipedia もめくっておこう。
Mixin は、メソッドが実装されたインターフェースとして見ることもできる。
…(中略)…
Java や C# などの一般的な言語では、Mixin の機能の一部は、インタフェースにより提供される。しかし、インタフェースはクラスがサポートしなければならないものを指定するのみで、実装を提供しないため、ポリモーフィズムを提供するためにのみ有用である。インターフェイスに依存し実装を提供するクラスが、共通の振る舞いを一箇所にリファクタリングするために有用である。
インターフェイスをアスペクト指向プログラミングと組み合わせた場合 C# や Java などの言語で完全な Mixin の機能を提供できる。
もう一声、あともうすこし説明が欲しいところ。Ruby が Mix-in を直接サポートしているらしいので、そこからたぐり寄せてみる。次の記事が特に参考になるか。1 ページまるごと重要そうに見えるので引用はしない。
まつもと直伝 プログラミングのオキテ 第3回(3):ITpro
ふむふむ。なんとなくわかったような。つまり、単一継承と多重継承のいいとこ取り、すなわち、継承によるクラス階層をツリー状に保ったまま複数のクラスから実装コードを取り込みたい、その要求を満たすためのテクニックが Mix-in という手法であると。
C# で Mix-in
なるほど。つまり、最初に挙げた一連の記事で言われていることとは、空のインターフェースに拡張メソッド(Extension Methods)を足すとそれって Mix-in クラスだ(module とみなせる)よね、ということだったんだな。
うん。おおよそ理解できてきたような気がするので、コード書いてみることにしよう。
/*
* ある種の実験的なコードです。.NET のネーミング ルールも無視しています。
*/
/// Mix-in クラス(その1)
public interface PrintableMixin {}
public static class PrintableExtentions
{
public static void Print<T>(this PrintableMixin print, T obj)
{
System.Console.WriteLine(obj.ToString());
}
}
/// Mix-in クラス(その2)
public interface DummyDataMixin {}
public static class DummyDataExtentions
{
public static string GetStringValue(this DummyDataMixin dummy)
{
return "Foo";
}
public static int GetIntValue(this DummyDataMixin dummy)
{
return 1;
}
}
/// Mix-in クラスの実装クラス
public class Hoge : PrintableMixin, DummyDataMixin
{
}
class Program
{
static void Main(string[] args)
{
Hoge hoge = new Hoge();
hoge.Print(hoge.GetStringValue());
hoge.Print(hoge.GetIntValue());
}
}
おお。動いた。あまりよい例ではないけど。Mix-in できたっぽい(これがモノホンの Mix-in なのか、擬似でしかないのか、いまいち判断できないので「ぽい」って語尾が外せないというこの悲しさ)。
エクステの可能性
拡張メソッドは既存のクラスにメソッドを付け加える。インスタンス メソッドのように見えて、インスタンス メソッドのように使うことができるが、それは見せかけでしかなく、実際にはそれは別の static クラスに定義された static メソッドでしかない。
だから、本来メソッド実装を持たないものに対しても、インスタンス メソッドのように見えるものを持たせることが可能になる。たとえば、メソッド実装を持つ enum。たとえば、メソッド実装を持つ interface。従来存在し得なかったオブジェクト達が新たなる地平を切り開くのだ。
と、大風呂敷を広げてみたものの、この Mix-in がハマる場面もそう多くはないだろうけど。ただ、知っておいても損はしないというか、なんかお得感があるよね。
(完全に余談)ところで、F# が将来のために reserve しているキーワードの中に mixin て単語が見えて非常に気になるんだけれども、そのうち言語機能として実装されたりするんだろうか。どうなんだ。
関連記事
- [C#] ダイアモンドだね (2008/05/24)