2009年2月26日木曜日

継承される事が前提のクラスに、自分が何者か教える方法

スキップリストのライブラリを作る時、ノードクラスには、ユーザがカスタムして使う事を前提にバーチャルメソッドをいくつか用意した。この時、スキップリストのコンテナクラスは、アイテムを引数として受け取り、ノードを生成してリストに追加するメソッドを持つ。問題は、この、ノードの生成という処理はノードクラスの静的メソッドであるべきだという事だ。すると、ノードクラスの基底クラスに、型パラメタとして、``自分が何者であるかを教えてやる''必要が生じる。少し変態的なコードになるが、面白いテクニックなのでまとめておく。

まず、スキップリストのコンテナクラスはこんな感じだ。

public class SkipList<TItem, TNode>
where TItem:class
where TNode:SkipListNode<TItem, TNode>, new()
{
TNode header, footer;
public SkipList()
{
header=SkipListNode<TItem, TNode>.CreateHeader();
footer=SkipListNode<TItem, TNode>.CreateFooter();
...
}
public void Insert(TItem item){
...
TNode newNode=SkipListNode<TItem, TNode>.CreateNode(item);
}
}

んで、ノードクラスはこんな感じだ。

public class SkipListNode<TItem, TNode>
where TItem:class
where TNode:SkipListNode<TItem, TNode>, new()
{
private TNode thisNode;
private TItem item;
private bool isHeader, isFooter;
public static TNode CreateNode(TItem item)
{
TNode newNode=new TNode();
newNode.thisNode=newnode;
newNode.item=Item;
newNode.isHeader=false;
newNode.isFooter=false;
return newNode;
}
public static TNode CreateHeader()
{
TNode newNode=new TNode();
newNode.thisNode=newnode;
newNode.item=null;
newNode.isHeader=true;
newNode.isFooter=false;
return newNode;
}
public static TNode CreateFooter()
{
TNode newNode=new TNode();
newNode.thisNode=newnode;
newNode.item=null;
newNode.isHeader=false;
newNode.isFooter=true;
return newNode;
}
...
他のメソッド(TNode型での自身への参照が欲しければthisでなくthisNodeフィールドを使う)
...
バーチャルなメソッドとかバーチャルなプロパティとか
}

使い方としては、

MyNode:SkipListNode<MyItem, MyNode>{
オーバーライドしたりプロパティを追加したり
}
...
クラスの定義の中で
SkipList<MyItem, MyNode> myList=new SkipList<MyItem, MyNode>();
...

などと使う。

特に、SkipListNode<TItem, TNode>の定義中でthisと書くとその型はSkipListNode<TItem, TNode>型になり、TNode型にならないので、TNode型のthisNodeフィールドを用意する事で、実行時の余計なキャストが必要なくなる。さりげないがここ超重要。

私が知った事

物事は難易度に従ってシーケンシャルに並んでいるものではない。合理的であるか非合理的であるか、可能であるか、不可能であるか、二値の命題によって特徴付けられる。その真理値があまりに人と食い違うとコミュニケーションがとても困難になり、自分の人生、自分の選択について人に説明できないという事態が生じる。そのために、便宜的に難易度というシーケンシャルなパラメタが社会/コミュニティによって導入される。

問題になっているのが因果関係ならば自由意志によって対処できる。問題になっているのが統計であるのならば逃れる事はできない。しかし人は自分の人生が上手く行っている限りはあまねく人は自由意志によって行動を選択すると考えたがる傾向を持つ(例えば先日の麻生総理の医療費問題に関する発言)。

それでも私には、未だ出来る事はあるし、自由意志を用いる余地も存在する。人のキャパシティとは、かくも大きく、そして小さい。