- PR -

taglibでMapにアクセス

投稿者投稿内容
Jumpin'' Jack Flash
大ベテラン
会議室デビュー日: 2006/01/24
投稿数: 198
投稿日時: 2006-07-13 22:38
引用:

nagiseさんの書き込み (2006-07-13 22:04) より:
背景が見えませんが、V get(Object key)ではなく、
Object get(Object key)だったらいいな、とおっしゃってますか?



良いとは思っていません。
V get(K key)であるべきだと思っています。
でも、V get(Object key)になっているので、
どうせなら、Object get(Object key)だったら、
とりあえずコンパイルを通せるのにと思ったまでです。

引用:

もし、単にvalue側をObject型として扱いたいのであれば
HashMap<String, Object>とすればよいのではないですか?



逆になぜそういう発想になるのかわからないです。
Object型をputするのは、taglibのアクセスの都合です。
Hogeクラス自体は、Stringのvalueしかputさせたくない
のです(このクラスを使う人に)。
そういう意味ではdataをputすること自体がNGなので、
dataは外出しにするのが正しい設計変更だと思いました。
コンパイルが通らないという理由でObjectクラスを乱用
するのは危険な行為だと思います。

引用:

valueの型を可変にしたいのであれば、
public class Hoge<V> extends HashMap<String, V>
でよいでしょうし。



valueの型を可変にはしたくないです。
あくまでもStringです(このクラスを使う人向けには)。

引用:

extends HashMapしている点も含めて、データの構造の設計が
危ういように思えますが…。



設計が危ういのは、おっしゃるとおりですね。
ちょっと考え直してみますが、
extends HashMapすると、データの構造の設計が危うい
というのはどういうことでしょうか?
すいませんが、教えてください。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-07-14 09:14
引用:

設計が危ういのは、おっしゃるとおりですね。
ちょっと考え直してみますが、
extends HashMapすると、データの構造の設計が危うい
というのはどういうことでしょうか?
すいませんが、教えてください。



extends HashMapの点ですが、継承を使うべきかどうかの指針である、
A is B および A has B の話になります。
継承関係(A extends B)にするにはAがBである、といえないといけません。
今の場合、Hoge extends HashMapですから、Hogeクラスは
HashMapが使われるシーンで代用可能でなくてはなりません。

しかし、一般に実装をもったコレクションクラス、つまりHashMapなどですが
これを継承して新たにコレクションを作る必要性というのはレアな事例です。
通常はA has B つまり、HogeはフィールドとしてHashMapを持っている
という構造で十分であり、またそうするべきです。


次に、ジェネリクスの件ですが、キーと値が<String, String>なのであれば
それを扱う場所はすべて<String, String>として統一するのが基本です。

引用:

this.put("data", this.data);

return this.data;
もエラーです。



とありましたが、this.dataがStringであれば問題ないはずです。
ここがそもそもStringにならないほうがおかしい。
もし、メソッドシグニチャの関係などでObject型などで得る場合でも、
return (String)this.data;
とできなくてはならない。
キャストの安全性はそのクラス内部でthis.dataに必ずStringが
入るように出入り口を押さえることで確保しましょう。
もし、this.dataの(宣言型ではなく)実態がString型ではないのなら、
それは扱うデータが誤っていることになります。
Jumpin'' Jack Flash
大ベテラン
会議室デビュー日: 2006/01/24
投稿数: 198
投稿日時: 2006-07-14 14:54
extends HashMapの件、詳細なご説明、ありがとうございました。
非常によくわかりました。
昔、なんで Propertiesクラスは Hashtableを継承してるの?
とか、なんで Stackクラスは Vectorを継承してるの?
と思ったものです。
今回のHogeも最初は「A has B」で設計していたのですが、
taglibで書くとELが長くなるので、「継承してみては?」と
考えたところから間違っていたようです。
これだけ、悩まされると、taglibの設計が良くないのではないか
と八つ当たりしてしまいます。実際、設計の良さと使い勝手の
良さは反比例することもしばしばありますから。

引用:

次に、ジェネリクスの件ですが、キーと値が<String, String>なのであれば
それを扱う場所はすべて<String, String>として統一するのが基本です。



taglibの仕様上、統一できなかったという見解なのですが。

/* このブロックはコメントアウト
taglibの
----
hoge.data → hoge.get("data"); // hogeがMapの場合
----
この仕様が
----
hoge.data → hoge.getData();
getData()メソッドがなければ、hoge.get("data");
----
であれば、何も悩まなかったんだけどなぁ。
*/

引用:

引用:

this.put("data", this.data);

return this.data;
もエラーです。



とありましたが、this.dataがStringであれば問題ないはずです。
ここがそもそもStringにならないほうがおかしい。
もし、メソッドシグニチャの関係などでObject型などで得る場合でも、
return (String)this.data;
とできなくてはならない。
キャストの安全性はそのクラス内部でthis.dataに必ずStringが
入るように出入り口を押さえることで確保しましょう。
もし、this.dataの(宣言型ではなく)実態がString型ではないのなら、
それは扱うデータが誤っていることになります。



this.data が Stringであれば、そもそもthis.dataという
フィールドを持つ必要がありません。
HashMap<String, String>を継承しているHoge(this)に
突っ込めますから。
String ではないデータは別途、HashMap<String, Object> data
に特別に持たせることを可能にしたのです。
なぜそうなったのかは話せば長く、設計の非を認めています
ので、このくらいでやめておきます。

親切に説明していただき、ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)