.NET Expert #02 に
id:yaneurao:20051231#p1によれば、
C#1.0/2.0のようにinterface継承しか出来ない言語系においてmix-inは必要不可欠な機能なのだがC#2.0ではmix-inは実装されていない。これをどう解決するか?という記事を技術評論社の(2006年1〜2月発売の)「.NET Expert #02」に書く予定だ。
ということらしい。perl や JavaScript*1みたいなプロトタイプ型や、C++ のような複数の実装の継承を許す言語ではない場合、なんらかの仕組みを導入する必要がある。このあたりは Java 関連をあたると色々なアイデアがあって勉強になる。
以下、どうでもいいこと。
使う側からの要件として、「実行時に透過的に動作するだけなのか、設計時にも透過的にアクセス可能なのか」という問題がある。多くの対応では、interface などを利用して実装を作成し実行時に解決を行うということが多い。これは、
public interface Ixxx { // またこれかよ! public void Save(Stream stream); } // Xxx は Ixxx を実装しない [Serializable] [Mixin(typeof(SaveSerializable)] public class Xxx { public void Hello() { ... } } // Serializable な型を保存する実装をもつ Ixxx の実装 public SaveSerializable : MixModule, Ixxx { public void Save(Stream stream) { } } code { // 通常、絶対に失敗するが、Xxx に SaveSerializable を mix することで // 実行時にこれが成功してしまうフレームワークが裏に存在する Ixxx = xxx as Ixxx; xxx.Save(...); }
というような形式だ。これは設計時に透過的にアクセスできないが、タイプセーフなプログラミングを維持した開発を行うことができるので大きな問題にならない。.NET でも Java でも、生成された静的な型に対してのみ設計時に透過的なアクセスを提供するというパターンもある。
つまり、上記の Xxx クラスを実装し終えた段階において、Visual Studio なんかで
code { Xxx x1 = new Xxx(); x1. }
と、"x1." をタイプした場合に得られる補完リストは、Hello() だけでなく Save() を含んでいるというパターンだ。これは設計時に透過的であるといえ、.NET の標準ライブラリでは正規表現や XmlSerializer がこの手法を利用して外部参照においてのみ設計時の透過的なアクセスを実現している。
この手のタイプの特徴として、一旦アセンブリ*2を生成してから、それを専用のツールで後処理して完成したアセンブリを生成するというパターンが多く、その専用のツールを使用することによって制約があったりする場合や、アセンブリを加工する他のツール(署名や難読化、ウォーターマーキングなど)との相互運用に問題があったりする場合がある。
その他 .NET 固有では「 FullTrust でしか動かない!」ってのは勘弁してもらいたいところ。
というわけで
やねうらおせんせいの記事に期待しつつ、#01 も見てないな…とか思ったり。