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
- ¦
- 停電