JavaでIoの構造っぽいものを(超簡単に)書いてみる

超簡単に、ですよ。循環継承はループから抜け出せませんので。

オブジェクトには、slotマップとprotosリストがあって、slotでそのオブジェクトが独自に持つデータを管理し、protosでそのオブジェクトの親オブジェクトを管理する。slotが呼ばれた場合、自分のslotにあればそれを返却し、なければ親オブジェクトを参照し、あればそれを返却する。だから、親オブジェクトのslotにあるキーと同名のキーでslotを追加すると、自分とこのslotで管理している値を返す。

委譲で継承を実現してるような感じ。

slotは値だけじゃなくメッセージ、つまりメソッドも管理できる。んだけど、その辺はまぁ取り合えず的に。

import java.util.*;

class Lobby {
    static final IoObj Object = new IoObj();
    
    public static void main(String[] args) {
        //Ioオブジェクトのクローンを作成
        IoObj a = Object._clone();
        a.setSlot("name", new IoValue<String>("わさお"));
        a.slot("name").println();   //prints "わさお"
        
        //aのクローンを作成して、スロット追加
        IoObj aa = a._clone();
        aa.setSlot("age", new IoValue<Integer>(10));
        aa.slot("name").println();  //prints "わさお"
        aa.slot("age").println();   //prints "10"
        
        //親オブジェクトのスロットを勝手に変更
        a.setSlot("name", new IoValue<String>("わさわさ"));
        aa.slot("name").println();  //prints "わさわさ"
        
        //子オブジェクトに同名のスロットを追加
        aa.setSlot("name", new IoValue<String>("わさこ"));
        aa.slot("name").println();  //prints "わさこ"
    }
}

class IoObj {
    /** slot */
    final Map<String, IoObj> slot = new HashMap<String, IoObj>();
    /** protos */
    final List<IoObj> protos = new ArrayList<IoObj>();
    
    /** このオブジェクトをprotosに持つ、新たなIoオブジェクトを作成して返却。*/
    IoObj _clone() {
        return new IoObj().appendProto(this);
    }
    
    /** 指定したスロットに格納されるIoオブジェクトを返却。*/
    IoObj slot(String name) {
        IoObj ret = recursiveLookup(name);
        if (ret != null) return ret;
        throw new RuntimeException("this does not respond to '"+name+"'");
    }
    
    /** 再帰的にスロットを検査する。 */
    private IoObj recursiveLookup(String name) {
        if (slot.containsKey(name)) return slot.get(name);
        for (IoObj proto : protos)
            if (proto.recursiveLookup(name) != null)
                return proto.recursiveLookup(name);
        return null;
    }
    
    /** 指定したスロットに、指定した値をセット。スロットがなければ作成する。 */
    IoObj setSlot(String name, IoObj value) {
        slot.put(name, value);
        return value;
    }
    
    /** 親オブジェクトを追加する。 */
    IoObj appendProto(IoObj proto) {
        protos.add(proto);
        return this;
    }
    
    void println() {System.out.println(this);}
    
    @Override public String toString() {return protos+":"+slot;}
}

class IoValue<T> extends IoObj {
    final T value;
    IoValue(T value) {this.value = value;}
    @Override public String toString() {return String.valueOf(value);}
}