# どうもサーバの調子が悪いようで……
まずSEさんにお願いですが、投稿に返信を付ける際には各投稿の右上にある
「返信」リンクを使ってください。そうすることでスレッドがつながりますので
[この投稿を含むスレッドを表示]をクリックすると関連する投稿をまとめて
読むことができます。
この掲示板の上のほうにある「スレッド順インデックス」をクリックすると、
他の投稿はちゃんとスレッドがつながっているのに、SEさんの投稿だけ
切り離されていることがわかるでしょう。
http://kmaebashi.com/bbs/thread.php?boardid=kmaebashibbs
>>まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は
>>ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて
>>いただきたいです。
>「マルチプルインスタンスがオブジェクト指向」と言う論理です。
>マルチプルインスタンスと言うのが何を指すのがよく分かりませんが、
>状態(内部の変数の値)の違う複数の処理群(クラス)と解釈しました。
「状態(内部の変数の値)の違う複数の"オブジェクト"」ですよね?
まあ、クラスベースのオブジェクト指向ではオブジェクトの生成の雛形として
クラスを使うわけで、「疑りぶかい~」ではクラスベースのオブジェクト指向の
話しかしていないわけですけれども。
実のところオブジェクト指向という用語は定義などないも同然なのですが、
「状態(内部の変数の値)の違う複数の"オブジェクト"を持てること」が
たいていのオブジェクト指向の定義の必要条件である、ぐらいのことはたぶん
言ってもよいでしょう。
で、そうするとなぜ「マルチプロセスやマルチスレッドはオブジェクト指向になる」
のですか?
「DOSを乗っけたPCを2台もってこれば同時に複数のプログラムを動かせるので、
DOSはマルチプロセスだ!」という主張は誰もしないと思いますけど。
>>・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのかわからなくて危険。
>引数の型を見れば分かると思います。
void hoge(Stack s) {
……
}
というメソッドがあったとき、sがStackなのかUpperStackなのかは
「わからない」と思いますが?
>>・別の誰かがLowerStackを作ったら、いつかマージするの?
>もし別機能として作るなら、Stackを継承してLowerStackを作ります。
>例えば大文字にした後に先頭に0を付加するような、UpperStackの処理結果に追加する物なら、
>UpperStackを継承して作ります。
>すでにLowerStackが出来てしまっているならマージしません。
で、同一インスタンスのスタックに放り込んだデータについて、ある場所では
大文字で取り出したいし、ある場所では小文字で取り出したい、という場合、
どのクラスを使えばよいのですか?
>>「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」
>>ということにしたいのでしょうか?
>そうです。
だとすれば比較対象にget(boolean up)を持ってきているのはおかしいですね。
get(boolean up)を使う人は、大文字が欲しいとき、意識して引数にtrueを
渡さなければならないからです。
774RRさんへの返信に
>ダウンキャストでなく、newするときに新しいクラスを使うと考えてください。
とありますが、(かなり離れた場所でnewされたかもしれない)Stackが
UpperStackなのかStackなのかを意識しなければ、UpperStackのget()を
便利に使うことはできません。SEさんの主張は矛盾しています。
>>この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、
>>「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる
>>既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。
>既存コードはソースに手を入れないので、影響はないと思いますが。
既存コードに引数でUpperStackを渡したら、入れたものを勝手に大文字に
変換するおかしなStackが紛れ込むことになります。ここではそういうことを
書いています。
>もう少し分かりやすい例をあげます。
Javaのコレクションクラスライブラリは、StackがVectorを継承していたりして
いろいろトホホなので、「良い例」として出せるものではないと思います。
現実的に許容範囲内の例ではあるかもしれませんけど。
で、LinkedHashMapやTreeMapですが、これらがHashMapを継承してしまったために、
・同じコレクションに対し、ある時は入力順に表示したいし、ある時は
ソートして表示したい、という場合どうすればよいのか?
(要件としてはすごくありそうだと思いますけれども)
・サブクラスにアクセスさせるために、HashMapのフィールドであるtableが
パッケージアクセスになってしまっているがこれはカプセル化の破壊では
ないのか。
(protectedにしなかったのはSunのエンジニアの良識だと思います)
・ていうかLikedHashMapではaddEntryとかcreateEntryとかパッケージアクセスの
メソッドをばんばんオーバーライドしているけれど大丈夫か(スーパークラスの
実装に強く依存している)。
といった問題があるわけです。
それでもまあなんとか「現実的に許容範囲」なのは、オーバーライドした
メソッドが、スーパークラス側のメソッドに対し「最低限同等の責務を果たす」と
いうオーバーライドにおける大原則を守っているからでしょう。
その点においてもSEさんのUpperStackはだめです。同じget()でありながら、
勝手に大文字に変換してしまうためです。
で、
>Map<String, String> mp = new LinkedHashMap<String, String>();
ここでMapに代入しているのはなぜですか?
入力順に出てくることを期待するのなら、LinkedHashMapのまま持ち歩くほうが
安全です。あるMapがLinkedHashMapのつもりだったのに実はそうでなかった、
というケースは、プログラムが大きくなって、newする場所と使う場所が離れれば
離れるほどいくらでも発生することです。そうなってしまえば、入力順に
取り出せないのですから致命的な上、コンパイルエラーどころか実行時のエラーも出ず、
黙って間違った順番でデータを吐き続けることになります。
これを避けるには、ダウンキャストするか、instanceofでクラスを確認する
必要があるでしょう。危険ですけれども。774RRさんがおっしゃっているのは
そういうことです。
Mapに代入するメリットと言えば、たとえばMapの中身をダンプする
void dumpMap(Map m);というメソッドに対し、LinkedHashMapを渡せば
入力順に表示されるしTreeMapを渡せばソートして表示される、という動きを
期待したいときでしょう。でもこれは、dumpMap()という既存メソッドに
新たに開発したオブジェクトを混入させることに他ならず、それでうまく
動くかどうかは保証の限りではありません。『「異物」が実行時に紛れ込む』と
書いたのはそういうことです。
# これをうまく動かすためには、やはり先ほどの「オーバーライドにおける大原則」
# を守る必要があるわけです。
で、
>ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの
>でしょうか。
これについては答えていただけないのでしょうか。ぜひ書名を教えて欲しいのですけれども。