上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

役に立ったらぽちっとよろしく。 人気ブログランキングへ

あるフレームワークが文脈情報をあっちからこっち、こっちからあっちと運んでいる時、自分の作ったデータも一緒に運んでもらいたい時がある。そう、無人島で遭難した時に、海流に乗って流す小瓶みたいなもん。たぶんフィリピン位で流すとだいたい黒潮に乗って日本にやって…くる…らしい…?

動的な型付けを持つ言語では、これは簡単で単に文脈情報にプロパティを追加すればいい。これで普段通り。なんだけど、Javaのような静的型付けを持つ言語は、Mapを使う事になる。ServletやJSFでのリクエスト属性やセッション属性がこれに当たる。で、何が嫌かと言えば、Mapにはいくつか不便な点があって、普段通りプロパティにアクセスするのと大きく違ってしまう。

  • まず、Mapのキーが文字列の場合。そう、さっきのビンに「鈴木太郎です。遭難しました。」と書いても、一度に二人以上、鈴木太郎さんが遭難してたらば、もう一方の関係者は激怒するに決まってる。何故、社会保障番号を導入しないんだ!!と。…まぁJavaでは大概FQCNという、一意になる名前を使うけど、もしかすると何も食べてないせいで自分の名前すら間違うかもしれない。
  • 次に、仮に全世界社会保障番号みたいなのを書いたタグを持っていたとして、それをさっきのビンに入れたとして今度は、「Oh!! 何て書いてますか?ワカリマセ~ン!! Sorry!!」 「HaHaaa!!、ジョーン、島の地図があるじゃないか!それはその島の観光協会のCMさ~!」 「Oh!! But!! ハワイ is No.1!だからイリマセーン!」って事になりかねない。

つまるところ、一意性のあるキーとその取り扱い(型)を示す情報が必要だと思うわけ。これがないとせっかく静的な型付け言語なのに、動的な型付け言語と同じように気をつけて情報を取り扱う事になる…。

追記の記事にバグ…詳しくは次の記事を[2009/3/1]…m(_ _)m

役に立ったらぽちっとよろしく。 人気ブログランキングへ


こんなんどやろか?

TypedKey.java


/**
 * キーに対する値の型が様々な場合、それらを安全に取り扱えるようにします。
 * 
 * @see MixValues
 * @param <V> 対応する値の型
 */
public final class TypedKey<V> implements Serializable {
    private static final long serialVersionUID = -3622510320414175893L;
    private final Class<V> clazz;

    /**
     * 与えられた型情報を持つキーを生成します。
     * 
     * @param <V> 対応する値の型
     * @param clazz 動的な型情報
     * @return 指定されたキー
     */
    public static <V> TypedKey<V> get(Class<V> clazz) {
        return new TypedKey<V>(clazz);
    }
    
    /**
     * 対応する値の型を取得します。
     */
    public Class<V> getValueClazz() {
        return clazz;
    }
    
    // コンストラクタ
    private TypedKey(Class<V> clazz) throws NullPointerException {
        if(clazz == null)
            throw new NullPointerException("clazz == null");
        this.clazz = clazz;
    }
    
}

MixValue.java


/**
 * 様々な型の値を格納するマップのような構造を提供します。
 * 
 * <p> キーに型情報を持たせる事で間違ったキャストを行うことを予防します。 </p>
 * 
 * @see TypedKey
 * @param <V> 格納される値の型
 */
public class MixValues<V> implements Serializable {
    
    private static final long serialVersionUID = 6081742018775950893L;
    private Map<TypedKey<? extends V>,V> map = new HashMap<TypedKey<? extends V>,V>();
    
    /**
     * 指定されたキーの値を取得します。
     */
    public <CV extends V> CV get(TypedKey<CV> key) {
        return key.getValueClazz().cast(map.get(key));
    }
    
    /**
     * 指定されたキーの値を設定します。
     */
    public <CV extends V> void put(TypedKey<CV> key, CV value) {
        map.put(key, value);
    }
    
    /**
     * 指定されたキーが含まれているかどうかを取得します。
     */
    public boolean containsKey(TypedKey<? extends V> key) {
        return map.containsKey(key);
    }
    
    /**
     * キーと値のペアをマップとして取得します。
     */
    public Map<TypedKey<? extends V>, V> getMap() {
        return Collections.unmodifiableMap(map);
    }

}
スポンサーサイト
コメント
この記事へのコメント
コメントを投稿する

トラックバック
この記事のトラックバックURL
この記事へのトラックバック
Copyright © ふらふら技術者の日記 All Rights Reserved.
Powered by FC2 Blog
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。