2006/01/17
JavaでのVariant型?型不定な値の扱い
アリエルでのディスカッションからの抜粋です。
最初の質問は、
ユーザには多くの属性値があります。 AquaType(aka AirForm, Air-otype)同様、拡張属性を持ちます。 この拡張属性の扱いをJavaでどうすべきでしょうか? 要は、 Map<String, Foo> attributes; で属性名からFoo型の属性値を取れるようにしたいのですが、 Foo型をどうするかです。 Object型にして(アプリ側が)キャストするしかないのでしょうか。 Javaなら、何か素晴しい方法がありますか?
というものです。この質問に対して、C++オタクからの反応は、
C++だとboost::variantというのがあります。 > boost:variant v; > v.set(1); > std::cout << v.get<int>() << std::endl; みたいに使います。setInt()とかsetString()とかいちいち用意する代わりに、 parameterized typeで解決する手法ですが、 Java1.5のGenericで同じことができるかどうかは知りません。 class templateしかサポートしてなくて、function templateは使えなかった 気がするので駄目?それでも、helper class templateを使えばいけるかなぁと 思ったけど、newしないとobjectを作れない不便言語なので、こっちの線も辛いと ころ。やるとしたら、気持ち悪いけどこんな感じかなぁ。 > Variant v; > new Setter<int>(v).set(1); > System.out.println(new Getter<int>(v).get()); C++だとnewが要らないので、いくらかマシな見た目(とパフォーマンス)になります。 [追記] function templateが使えるっぽい。でも、genericの実装方法から考えると、 > public class Variant { > public <T> T get() {return (T)value;} > public <T> Variant set(T value) {this.value = value;} > private Object value; > } みたいなのはコンパイルが通らない気がする。
というものです。C++オタクはさらに調べて、
reflection(Class.cast() method)を使って、 > Variant v; > v.set(new Interger(1)); > Integer i = v.get("java.lang.Integer"); てのはどうだ。
となっています。ここで、別の人の回答として、
素晴らしい方法は知りません。そもそもJavaには存在しないのか、 それとも私が不勉強なだけなのかもわかりませんせんが。 キャストするか、サポートしている型を答える、その型で値を返す、 などのメソッドを用意した拡張属性の独自のInterfaceとかを作って使うか、 それくらいしか思いつきません。
とここで、ひと段落したかにみめましたが、C++オタクは
> public class Variant { > private Object value = null; > public Variant(Object value) { > this.value = value; > } > public get(String typeName) > throws ClassCastException, ClassNotFoundException { > return Class.forName(typeName).cast(this.value); > } > public set(Object value) { > this.value = value; > } > public set(int value) { > this.value = new Integer(value); > } > // declare for other primitive types. > } 無意味?
とコードを交えて切り返してきます。ここで、大人の回答が出てきます。
> 無意味? 無意味かどうかは、困ったなあ、と思われたご本人がどう評価されるかだと 思うのですが、そもそも、何に「困った」かですよね。 1. 属性値を利用する側で毎回キャストするのが面倒(あるいは無駄) 2. 型での制約が実質的に無効となってよろしくない という辺りなのかと想像するのですが、もっと深い意味があるのかもしれません (意趣返し)。 2の方の意味が強い場合は、難しいのではないでしょうか
となってきます。この困ったにもともとの質問者ではなくC++オタクが次のように答えています。
例えば、 > static String fooType = "java.lang.Integer"; > void bar(Variant v) { > Integer foo = v.get(fooType); > } とかやって使う。本質的にはtypedefの代わり。
となっています。JavaのVariantの議論に対して、今後の展開はどうなるのでしょう。
- Category(s)
- 開発
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/dev/java306evariant578b-578b4e0d5b9a306a5024306e62713044/tbping
- 須崎開発マネージャの怪しい週末疑惑
- ¦
- Main
- ¦
- 停電