K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[1295] Re:コード生成部分について
投稿者:(ぱ)こと管理人
2009/05/25 01:16:56

> {"push_int_4byte", "i", 1}, // 直接持に変更 > {"push_double_8byte", "d", 1}, // 直接持に変更 要点は、文字列以外はコンスタントプールを使わずに、直接定数を バイトコードの中に埋め込むようにした、ということですよね。 Diksamは、JVMを真似したのと、将来的にバイトコードをファイルに 吐き出すことを考えてコンスタントプールを持ちましたが、 たとえばYARVでは、効率を考えて定数をバイトコード(ていうかこれも 効率を考えてバイトコードではなくワードコード)中に埋め込んでいるそうです。 http://www.atdot.net/yarv/yarvarch.ja.html > {"push_sysval_int", "s", 1}, // システムグローバル変数アクセス用 > {"push_sysval_double", "s", 1}, // > {"push_sysval_str", "s", 1}, // > {"pop_sysval_int", "s", -1}, // > {"pop_sysval_double", "s", -1}, // > {"pop_sysval_str", "s", -1}, // あと、もしシステムグローバル変数がDVM_Valueを保持しているのなら、 実はpush_sysval_intやpush_sysval_doubleのようにインストラクションを 型ごとに分ける必要はありません。 Diksamの場合、スタックはDVM_Valueの配列のくせにこのインストラクションを 分けているのは、将来的にint型ローカル変数は4バイトしか消費しないようにする、 といった改善を入れるときのためです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1294] コード生成部分について
投稿者:
2009/05/24 19:18:12

 コード生成部分を作っています。基本部以外がほとんど新たなプログラムに なっています。下にバイトコードの変更およびコードのディスアセンブラです。  もしお時間が有りましたら見て、何か気になる点が有りますでしょうか? --- 修正したバイトコード ------------ {"push_int_4byte", "i", 1}, // 直接持に変更 {"push_double_8byte", "d", 1}, // 直接持に変更 // 今考えると、リアル値を持つのはまずい? --- 追加したバイトコード ------------ {"push_sysval_int", "s", 1}, // システムグローバル変数アクセス用 {"push_sysval_double", "s", 1}, // {"push_sysval_str", "s", 1}, // {"pop_sysval_int", "s", -1}, // {"pop_sysval_double", "s", -1}, // {"pop_sysval_str", "s", -1}, // -------------------------------------------------------- int main(int p1,int p2) { string[] msg = { "asd","qwe","zzz"}; int[] i1 = {1,2,65537}; double d1; d1 =3.1; } --------------------------------------------------------   ↓ コード生成後のダンプ   ↓   ↓ 上のコード修正で、constデータは文字列だけになりました。 -------------------------------------------------------- 1:*** 関数情報ダンプ ****************** 1:--- int main(int p1, int p2) 1:*** ローカル変数の表示 no = 3 *** 1: 0:string [] msg 1: 1:int [] i1 1: 2:double d1 1:*** 文字列定数 数 = 3 *** 1: 0: "asd" 1: 1: "qwe" 1: 2: "zzz" 1:*** 使用予定のスタックサイズ = 10 1:*** 関数コードのディスアセンブラ size = 45 1: 0 push_string_ptr 0 1: 3 push_string_ptr 1 1: 6 push_string_ptr 2 1: 9 new_array_literal_object 3 1: 12 pop_stack_object 2 1: 15 push_int_1byte 1 1: 17 push_int_1byte 2 1: 19 push_int_4byte 65537 1: 24 new_array_literal_int 3 1: 27 pop_stack_int 3 1: 30 push_double_8byte 3.100000e+000 1: 39 pop_stack_double 4 1: 42 push_int_1byte 0 1: 44 return 1:*** 行情報 数 = 5 *** 1: 3: from 0 size 15 1: 4: from 15 size 15 1: 6: from 30 size 12 1: 8: from 42 size 2 1: 7: from 44 size 1 1:*** end of main() -------------- --------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1293] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/23 13:51:39

>デザインパターンと言うのは、世の中にある数多くのOOで組まれたプログラムの中から、 >共通性のある物を抜き出して分類し、その特徴や利点/欠点を解析する学問的な物です。 >重要なのは解析する能力を付ける事です。 なるほど、「学問的な物です」というのはよくわかりませんが、 おっしゃりたいことはだいたいわかったように思います。 >誰かの分類したパターンと特徴を暗記しても意味はありません。 しかしこれを「意味はありません」と言い切っちゃうのはどうかと。 kitさんが既に書いておられますが、デザインパターンはパターンに名前をつけて プログラマ間のコミュニケーションに使うことに意味があるわけですから。 >ITproのHPの人も言っていますが、「言語」→「実践」→「デザパタ」と進むのが >いいと思います。実践無しでデザパタを見たら、大抵の人は勘違いすると思います。 ここに異論はありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1292] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/23 13:47:59

SEさんが何をおっしゃりたいのかますますわからなくなっていくのですが、 >ちなみに簡単に変更できた例は、 >メモリ上で頻繁に検索するデータが100件から6万件に変わった時の事でした。 >検索にキャッシュやヒストリー機能などあらゆる機能を組み込み高速化しましたが、 >修正したクラスは1つです。もしCの構造化で組んでいたら、修正箇所と影響範囲を >調べるだけで嫌になっていたと思います。 関連する操作やデータをまとめる、というのは普通にモジュール化であって、 私が「疑りぶかい~」で書いたオセロの例の、Cでstaticで隠蔽を行った board.cで達成していることでは? http://kmaebashi.com/programmer/object/othello.html 「疑りぶかい~」を書いたときの私の認識は、 「Cなどでプログラムを書いている普通のプログラマは、staticで情報隠蔽するような  モジュール化は普通に行っているだろう。でもそれは、オブジェクト指向ではない。  オブジェクト指向(C++流の)といえばカプセル化、継承、ポリモルフィズムと言われるけれど、  カプセル化は普通のCプログラマも理解していそうだし、継承やポリモルフィズムに  至る前にマルチプルインスタンスを理解しなければいけないのに、世間にあふれる  オブジェクト指向の説明からはそこがすっぽり抜けている。  多くの人がここで引っかかるように思うので、このミッシングリンクは埋めておく  べきではないか」 というものです。 この認識がズレている、という批判ならお受けしますけれども。 マルチプルインスタンスのさらに手前の事例を持ってきて、オブジェクト指向の 成果だと言われても…… 継承の話はどこにいったんでしょうか。 いや、「世間のCプログラマはstaticで実装を隠蔽するような気の効いたことは していない。だからお前の認識はズレているのだ」ということならそうなのかも しれませんけど(1ソースファイル1関数、という規約のプロジェクトとかって、 今でもあるんでしょうか)。 >普通のLoggerは、staticのフィールド変数として作成して直接使用するため、Logger自体を >メソッドの引数にして使用する事は少ないと思います。 うーん、Loggerくらいならstaticでもかまわないとは確かに思いますけれど、 私ならアプリケーションのインスタンスのフィールドに持ちますね。 オセロの例なら、Boardクラスで障害発生時とかのログを残すとして、Loggerは Boardに持たせます。名人戦のBoardだけ障害発生時の対応が違ったりするかも 知れませんし。よって、BoardのコンストラクタかsetLogger()メソッドの 引数でLoggerを渡すことになります。 >敢えてLoggerを例にするとすると、 >void write(Logger l){} >なら、 >class Logger{ >  void write(){} >} >にすべきと言う事です。 ええと、write()メソッドがログを吐くメソッドなら、 >class Logger{ >  void write(){} >} となるのは当たり前だと思うんですが……
[この投稿を含むスレッドを表示] [この投稿を削除]
[1291] Re:オブジェクト指向の概念の発明者は誰ですか?
投稿者:(ぱ)こと管理人
2009/05/23 12:26:48

件名変えました。 >アランケイの「メッセージ指向」は、C++の登場した当たりから軽視されるようになっていて、 >現在のオブジェクト指向の実装や環境から考えると、誤解しやすい物になっているからです。 >(ぱ)さんも「ただの関数呼び出し」と言っていますが、私もそう思います。 こくぼさんには「Smalltalkが不憫で仕方ありません」と言われそうですが、 職業プログラマである我々が、現状、仕事でSmalltalkを使うことはまあまずないわけで、 JavaやC++やC#を使うのに「メッセージ」がどうこう言われたら誤解を招く、というのは わかります。 で、当のsumimさんのページにはまさにそういうことが書いてあるわけで、 >なお、この文脈の「オブジェクト指向」において、メッセージングはぜんぜん関係ない >無用のもの and/or 動的性実現のための(仮想関数より効率の悪い)実装のひとつに >過ぎない…ということを強く意識する必要があります。ケイの影響で「オブジェクト >指向=メッセージ」と脳に染みついている人には酷かもしれませんが、いっそ排除して >考えたほうがすっきりしますし、可能な限りそうすべきです。 >しがらみのない初学者へのレクチャーに際しては、ぜひとも「オブジェクトにメッセー >ジを送って…」とか「世の中のあらゆるものを(ry」なんて説明は後々無用な混乱を >招くだけなので、やめて欲しいと思います。 なぜこのページについて >これもひどい内容ですね。 とSEさんがおしゃるのか、さっぱりわからないんですけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1289] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/22 16:57:12

デザインパターンと言うのは、世の中にある数多くのOOで組まれたプログラムの中から、 共通性のある物を抜き出して分類し、その特徴や利点/欠点を解析する学問的な物です。 重要なのは解析する能力を付ける事です。 誰かの分類したパターンと特徴を暗記しても意味はありません。 ただ私もGoFのパターンは見ました。学者的で実務に使えるのは2割程度だと思いましたが。 ITproのHPの人も言っていますが、「言語」→「実践」→「デザパタ」と進むのが いいと思います。実践無しでデザパタを見たら、大抵の人は勘違いすると思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1288] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/22 16:36:27

>アランケイの「メッセージ指向」は、C++の登場した当たりから軽視されるようになっていて、 >現在のオブジェクト指向の実装や環境から考えると、誤解しやすい物になっているからです。 >(ぱ)さんも「ただの関数呼び出し」と言っていますが、私もそう思います。 >歴史に関してはウィキペディアに詳しく記載されています。 あぁ…。抽象データ型のオブジェクト指向が現代のオブジェクト指向だと解釈されているのですね。 そこらへんの各人のオブジェクト指向への認識の違いを理解していただくことも含めて sumimさんの説明ページへとリンクしたつもりでしたが伝わってないみたいで…。 #Wikipediaの説明も見ましたがあれではSmalltalkが不憫で仕方ありません >オブジェクト指向自体の話ではありませんが、オブジェクト指向の間違いやすい所に関しては、 >以下の記載がかなりいい所をついていると思います。(全て賛成できる訳ではありませんが) >http://itpro.nikkeibp.co.jp/article/COLUMN/20060921/248617/?ST=develop&P=1 ザッと見ました。 このページを見る限りではSEさんが例示しておられる 実装継承を使ったオブジェクト指向プログラミングを推奨しているわけではなさそうですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1287] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/22 16:25:01

>関数等に切り出されて一箇所にまとめられていれば修正するのは一箇所です。 >ここまではオブジェクト指向は関係ありません。 ここがミソです。1つの関数を考えた場合はそうですが、関数群で考えると違います。 例えばファイル操作を考えてみましょう。 クラスなら以下のようになるとします。 class File{   public void open(){}   public void read(){}   public void write(){}   public void close(){} } これなら明確です。ファイルからメモりに変わっても簡単に変更できるでしょう。 しかしCの構造化なら関数同士の関連はありません。 そのため、もしかしたらread()は業務ロジックに組み込まれ関数化されていないかもしれませんし、 write()は3つに分割されているかもしれません。例がファイルなのでそんな簡単な間違いは しないと言うかもしれませんが、もしこれが業務ロジックなら簡単に判断出来ないかもしれません。 これが関数化(プロセス中心アプローチ(POA)または、データ中心アプローチ(DOA))と、 クラス化(オブジェクト中心アプローチ(OOA))の違いです。 POA、DOA、OOAの特徴と違いについては、以下のサイトがよく分かります。 (分かりにくい表現もありますが) http://itpro.nikkeibp.co.jp/article/COLUMN/20061019/251255/ ちなみに簡単に変更できた例は、 メモリ上で頻繁に検索するデータが100件から6万件に変わった時の事でした。 検索にキャッシュやヒストリー機能などあらゆる機能を組み込み高速化しましたが、 修正したクラスは1つです。もしCの構造化で組んでいたら、修正箇所と影響範囲を 調べるだけで嫌になっていたと思います。 Loggerのようないわゆる「横断的関心事」はOOに適さないので例としては良くないと思いますが、 普通のLoggerは、staticのフィールド変数として作成して直接使用するため、Logger自体を メソッドの引数にして使用する事は少ないと思います。 敢えてLoggerを例にするとすると、 void write(Logger l){} なら、 class Logger{   void write(){} } にすべきと言う事です。 >
[この投稿を含むスレッドを表示] [この投稿を削除]
[1286] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/22 15:27:15

>どこがひどいと思われるのでしょうか? >「この当たりの話は知っています」と書かれていることから類似のWebページなどをご存知なのでしょうか。 >できればその情報のソースを教えていただきたいです。 >(自分的にこの手の情報はsumimさんの日記くらいしか知らないので) アランケイの「メッセージ指向」は、C++の登場した当たりから軽視されるようになっていて、 現在のオブジェクト指向の実装や環境から考えると、誤解しやすい物になっているからです。 (ぱ)さんも「ただの関数呼び出し」と言っていますが、私もそう思います。 歴史に関してはウィキペディアに詳しく記載されています。 >#できれば他にもSEさんが比較的マシだと思ってる本やWebページを >#いろいろ教えていただきたいところですが オブジェクト指向自体の話ではありませんが、オブジェクト指向の間違いやすい所に関しては、 以下の記載がかなりいい所をついていると思います。(全て賛成できる訳ではありませんが) http://itpro.nikkeibp.co.jp/article/COLUMN/20060921/248617/?ST=develop&P=1
[この投稿を含むスレッドを表示] [この投稿を削除]
[1285] Re:>(ぱ)こと管理人さん
投稿者:yuya
2009/05/22 11:47:06

懐かしいお名前がいっぱいでうれしくなりました。 kitさんも >でも、そもそもデザインパターンの多くは、それなりのプログラマーだったら、 >自分で似たようなものを必要に応じて考えて既に使っているものですよね。 と書かれていますが、SEさんのご意見が、 「天下りに与えられたパターンを憶える(=学習する?)んじゃなくて、 自分で同じものを作ってみるなりしてきちんと理解する(=解析する?)べきだ」、 ということならば、賛成ですけどね。 議論の行く末が気になるので、SEさんにはまた登場していただきたいです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1284] Re:>(ぱ)こと管理人さん
投稿者:kit
2009/05/22 10:49:48

>ちょっと穿って解釈すると、 > > ちなみにデザインパターンは学習(に値)する(ような)物ではなく、 > (こんなものを調子こいて使ってしまうとソースが読みにくくなって > 必死に)解析する(ハメになるような)物です。 > >という意味なんでしょうか。 > >そういう趣旨ならわからなくはないし、部分的には賛同しないでもないのですが、 なるほど。 勉強したばかりで調子にのって *必要ないのに* 使いすぎると、問題は問題ですね。 でも、そもそもデザインパターンの多くは、それなりのプログラマーだったら、 自分で似たようなものを必要に応じて考えて既に使っているものですよね。 各種パターン本の意義は、そういうものにきちんと名前をつけて、いちいち説明 しなくても意思の疎通を可能にするという側面が大きいわけです。これにはソース 中の名前づけを標準化して、可読性を高めることを含みます。 したがって、経験のあるプログラマーにとって、デザインパターンの学習という のは、既知の設計手法について、規範となる名前を学習するという意味になります。 また、デザインパターンとして標準化された名前を使うことによって、ソース等を 解析することなく (すなわち、名前を見ただけで) モジュールの役割を理解する ことが可能になります。 また、もちろん初学者にとっては、設計パターンを自分で一から考える手間を省く という学習の意義があります。 というわけで、もしそういう意味だったとしても、やっぱり賛成できませんねえ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1283] Re:疑い深い・・・
投稿者:(ぱ)こと管理人
2009/05/22 02:16:37

横から口を出しますけど、 >>そもそも OO (というか継承-派生というシステム) のおいしいところは >>・「基底クラスを使う人」と「派生クラスを作る人」が分離できる >>・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい >>・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 >> 自動的に正しく使ってもらえる、と判断してよい >これが利点ですか?ちょっと他人に説明するのが難しいです。 前回私が例に出したLoggerクラスで考えると、 >>・「基底クラスを使う人」と「派生クラスを作る人」が分離できる 「Loggerクラスを使う人」は、logger.write()のようなメソッドを単に呼べばよく、 「ログをファイルに出力するFileLoggerクラスを作る人」と分離できる。 >>・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい 「Loggerクラスを使う人」は、logger.write()のようなメソッドを単に呼べばよく、 FileLoggerクラスについては知らなくていい。 >>・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 >> 自動的に正しく使ってもらえる、と判断してよい 「FileLoggerクラスを作る人」は、基底クラス側で期待している動作(=契約)に 反しない限り、自動的に正しく使ってもらえる、と判断してよい わけで、私から見れば、774RRさんはごく普通にオブジェクト指向の利点を 挙げていると思うんですけど。 もちろん、何にでも利点と欠点はあるものですし、その重み付けは用途によって 変わります。SEさんの過去の業務で実装継承がすごく役に立ったのなら、 それはそれで興味深いことです。 だからこそ、実際に役に立ちそうな現実的な例を挙げていただきたいと思いますし、 上記774RRさんが挙げられたような利点をあまり重視しておられないように見える割に、 [1260]のUpperStackにおいて、getUpper()のようなメソッドを作らずにget()を オーバーライドしていたり、 [1270]で >>「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >>ということにしたいのでしょうか? という問いに対して >そうです。 と答えていたり、 同じく[1270]で new LinkedHashMap<String, String>()の戻り値を Map<String, String>型の変数に代入したりしている 意図がさっぱりわからないわけです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1282] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/22 01:53:22

kitさん、おひさしぶりです。 >>>ちなみにデザインパターンは学習する物ではなく、解析する物です。 >> >>?? >>すみません、仰っておられる意味がわかりません…。 > >素直に解釈すると、SEさんは GoF本や PofEAA あたりも読んだことがないって >ことになります (こういった本を読むこと == デザインパターンを学習すること >ですから)。 私にもSEさんのおっしゃる意味はよくわからないのですが、ちょっと穿って解釈すると、  ちなみにデザインパターンは学習(に値)する(ような)物ではなく、  (こんなものを調子こいて使ってしまうとソースが読みにくくなって  必死に)解析する(ハメになるような)物です。 という意味なんでしょうか。 そういう趣旨ならわからなくはないし、部分的には賛同しないでもないのですが、 もしそういう意図なら、もっとわかりやすく書いていただきたいです……
[この投稿を含むスレッドを表示] [この投稿を削除]
[1281] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:
2009/05/21 21:05:59

>こちらの返信が遅くなってしまいました。 いえいえ、お返事いただけるだけで嬉しいので、気にしないでゆっくりして下さい。 >(私の感覚では)かなり実用的な問題でして。 了解しました >また、ヘッダファイルの依存関係が漏洩するという問題もあるでしょう。 >あるライブラリがウインドウに絵を描いたりするのでprivateメンバで >windows.hで定義されている型などを使っていたりすると、それを使う人にまで >もれなくwindows.hがプレゼントされ名前空間が汚染されてしまったりとか。 賛同です。これは問題ですね。OOP以前C言語の時は、それはキッチリとヘッダーが きれいに分割され必要な所だけが#includeされていたのですが。OOPになって、 必要も無いようなヘッダーが次から次へと#includeされているのを見るのは、 正直止めてほしいと思っています。特にVCはひどい、プリコンパイルヘッダーを 作ったのは苦肉の策ではないかと疑ってしまうほどです。  しかし、現実に自身が作っている内容でも、結局多くのヘッダーが#include してしまっているのを見るにつけ、何かの対策がほしいと思います。 >これを問題と思わない人が多かったようなので、私のような心配をするのは >少数派なのかもしれませんけれども。 私もそうですが、目をつぶっているだけなのかも知れません。  ちょっと真剣に考えて見ます。軽はずみな返事をしたくないと思っているので ちょっと期間をくださ。今は、作っている言語仕様に頭がいっぱいなんです。 いま佳境に入ってて、最近はプログラムではなく仕様書の書き込み書き直しばか りしています。楽しくもあり苦しくもある時間です。  いやほんと、こんな仕様を発表したら、けちょんけちょんにけなされっるので はないかとか、本当に良いんだろうかとか、でも当面第1弾はこれしかないよな~ とか、悩んだりしています。   今作っている言語そしてシステムの最大の目的は。   「簡単なルールを持った言語で、いかに複雑な処理を簡単に書けるか」 なので、熟練のプログラマーのほうが抵抗が大きいのではないかと…  プログラミング言語というものは論理的に整然と矛盾が無く、どんな形でも 記述可能であり。その中においてさえ、書きやすくセーフティーな環境を提供し 見やすさを追求している、と私は思っています。でも、私が目指しているのは。 記述目的を限定することで、自由が無くなる分、普通では考えられないような 記述で複雑なものを簡単に記述すシステムを出してみたい。  大風呂敷はこのへんで終わって、早く実物が出来るようにがんばります。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1280] Re:>(ぱ)こと管理人さん
投稿者:kit
2009/05/21 10:32:18

>>ちなみにデザインパターンは学習する物ではなく、解析する物です。 > >?? >すみません、仰っておられる意味がわかりません…。 素直に解釈すると、SEさんは GoF本や PofEAA あたりも読んだことがないって ことになります (こういった本を読むこと == デザインパターンを学習すること ですから)。 そう解釈していいんですかね?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1279] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:(ぱ)こと管理人
2009/05/21 01:45:56

SEさんとの議論がアツいので、こちらの返信が遅くなってしまいました。 > カプセル化という言葉に対して、きっちりとした完全な意味を求めてるのだ >ろうと思いますが、私はそこまでのことを意識してこの言葉を使っていません。 ええと、用語定義の問題と言うよりは、(私の感覚では)かなり実用的な問題でして。 > 必要なこと意外一切情報を出さないほうがいいのか。内部がある程度想像 >できるほうがいいのか?Cはたとえ使えなくともクラスのデータやメソッドが見 >える。これが良いか悪いかでしょう。私は後者のほうが気分的には良いです。 チームで開発するとき、ライブラリとそれを使うアプリケーションがあったとして、 これらを平行して開発することがあります。そういう場合、ライブラリの ヘッダファイルだけ先に作ってしまえばアプリケーション側のコンパイルが通せますが、 その時、空実装のメソッドを暫定で書いて後で差し替えるような作業は バージョン管理が面倒になるので避けたい。また、ヘッダファイルはドキュメント的な 性格も大きいですから、ここに実装やprivateメンバを書いてごちゃごちゃして しまうのも避けたい。 また、ヘッダファイルの依存関係が漏洩するという問題もあるでしょう。 あるライブラリがウインドウに絵を描いたりするのでprivateメンバで windows.hで定義されている型などを使っていたりすると、それを使う人にまで もれなくwindows.hがプレゼントされ名前空間が汚染されてしまったりとか。 ……という話題が昔JavaHouseであったとき、 http://java-house.jp/ml/archive/j-h-b/048357.html#body http://java-house.jp/ml/archive/j-h-b/048360.html#body これを問題と思わない人が多かったようなので、私のような心配をするのは 少数派なのかもしれませんけれども。 > 言語の設計において、理想的なものを作っていくのもあります。私の場合は >目的が実現できれば簡単なものでいいと思って設計しています。その代表が >#defineです。古い仕様で問題点も内包しますが、実に使いやすく融通が利きます。 >今では#defineはあまり良くないとされていますが、私は利点を選びました。 これは同意です。「わかって使う」分には、#defineは便利ですよね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1278] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/21 00:40:14

>大文字小文字の例が悪かったのか、話がそこから進まないようです。 では、よい例を出してもらえませんか。具体的な例なしでこの手の話をしても 意味がありません。 774RRさんへの返信に >例えば総合試験で性能目標に達しなかった場合、従来の方法では普通は大変更に >なりますが、オブジェクト指向の場合、一部のクラスの取得処理を変更しただけで >修正できた例もあります。 とありますが、これも具体的にどういうケースだったのかわかりません。 普通に考えて、どこかの処理がボトルネックになっていたのなら、そこだけ 書き直せば速くなるでしょう。もちろん、その処理がプログラムのあっちこっちに コピペされていれば大変更になるでしょうが、関数等に切り出されて一箇所に まとめられていれば修正するのは一箇所です。ここまではオブジェクト指向は 関係ありません。 オブジェクト指向であったがゆえにうまくいった、とのことなので、 関数化ではうまくいかないケースだったのでしょう。どういう理由で、関数化では うまくいかず、オブジェクト指向(実装継承?)でうまくいったのでしょうか。 仕事のソースをここに貼ることができないのはわかっていますが、概要だけでも 教えてもらえませんか。興味深いので。 >遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 >構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 オブジェクト指向の最大の特徴のひとつであるポリモルフィズムは、遠いところで newしたオブジェクトのメソッドを呼ぶと、呼ぶ側が意識しなくても、 そのオブジェクトに応じたメソッドが呼び出される、というものですよね? デザインパターンなどでは生成に関するパターンだけでいくつもあって、 うちいくつかは、具体的なクラスが何であるかを意識させないようにするための ものですし、DI(Dependency Injection)なんかも考え方はそっち方面です。 まあ、この手のことは、当面用途もないのに調子に乗って柔軟性を求めると ソースが追えなくなってしまうので、私はあまり好きではないのですけれど。 ありがちな例では、たとえばログを出力するLoggerクラスをabstractクラスもしくは interfaceとして作って、それを継承またはimplementsしてファイルに吐くLoggerや syslogに吐くLoggerを作ったりしますが、これは、遠く離れたところでnewした Loggerを引数等で持って回ることになると思うんですが。 >オブジェクト指向の場合は処理は関連するデータと共にクラスに >まとめられるため、その引数を必要とするメソッドを、引数のクラス内 >に実装できるか検討すべきです。 意味がわかりません。 さっきのLoggerの例で言えば、Loggerクラスを引数として受け取るメソッドは Loggerを使うアプリケーションですが、アプリケーションのメソッドを Loggerクラスの中に作れ、という主張……ではないですよね。 >>ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >>でしょうか。 こくぼさんからも質問が出ていますが、私もSEさんが「比較的マシ」だと思ってる 本やWebページを教えていただきたいです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1277] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/20 18:32:43

>ちなみにデザインパターンは学習する物ではなく、解析する物です。 ?? すみません、仰っておられる意味がわかりません…。 >これもひどい内容ですね。 詳しく教えていただきたいのですが、 どこがひどいと思われるのでしょうか? 「この当たりの話は知っています」と書かれていることから類似のWebページなどをご存知なのでしょうか。 できればその情報のソースを教えていただきたいです。 (自分的にこの手の情報はsumimさんの日記くらいしか知らないので) >これならまだ「ウィキペディア」の「オブジェクト指向プログラミング」の >方がマシです。 >一度読んでみてはいかがですか? ありがとうございます。 読んでみます。 #できれば他にもSEさんが比較的マシだと思ってる本やWebページを #いろいろ教えていただきたいところですが
[この投稿を含むスレッドを表示] [この投稿を削除]
[1276] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/20 15:47:40

>デザインパターンを学習されているなら継承を使う機会は減ると思うんですけど。 >#減るというか注意深くなるというか デザインパターンは知っています。 ちなみにデザインパターンは学習する物ではなく、解析する物です。 >ちなみにこのページはオブジェクト指向を学ぶうえにおいてとても参考になります。 >一読してみてください。 >http://d.hatena.ne.jp/sumim/20040525/p1 これもひどい内容ですね。 この当たりの話は知っていますが、参考にするのはまずいでしょう。 これならまだ「ウィキペディア」の「オブジェクト指向プログラミング」の 方がマシです。 一度読んでみてはいかがですか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1275] Re:疑い深い・・・
投稿者:SE
2009/05/20 15:31:59

>俺も (ぱ) 氏ももっとマクロな=大規模プログラムでの応用の話をしているわけです。 >そういうレベルでは、提示のコードのような派生はうまくいきません。 なぜ大規模プログラムでうまくいかないのかが分かりません。 実際、大規模プログラムで使用していますが、効果が出ています。 例えば総合試験で性能目標に達しなかった場合、従来の方法では普通は大変更に なりますが、オブジェクト指向の場合、一部のクラスの取得処理を変更しただけで 修正できた例もあります。 オブジェクト指向ではオブジェクト単位であるため、大きいレベルから小さいレベル まで対応できるのが特徴です。 >そもそも OO (というか継承-派生というシステム) のおいしいところは >・「基底クラスを使う人」と「派生クラスを作る人」が分離できる >・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい >・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 > 自動的に正しく使ってもらえる、と判断してよい これが利点ですか?ちょっと他人に説明するのが難しいです。 私の例では、処理に大修正が入った場合(例えばDB変更や、ローカルファイルから 通信を使ったリモートファイルへの変更)、これだけの修正で済みますなどと 言えますが、上記の場合はどう説明しますか? >んで、マルチプルインスタンスの件のほうはもういいのでしょうか? >俺としては既に書いたとおり「対象読者層が異なる」というだけの話だと思っております。 了解しました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1274] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/20 14:40:28

スタックの例とかあんまり細かく見ずにコメントしますが…。 >それぞれ用途が違いますが、オブジェクト指向特有で強力なのが2,3です。 >別に全て2でやれと言っているわけではなく、2の使い方が出来るのが >利点だと言っている訳です。 >... >つまり、分かりやすいとか間違えやすいとか言う話は別として、 >4種類の変更方法を選択できるため、再利用性が高いと言っている訳です。 そもそも継承というメカニズムを使うのが間違いのもとになっちゃうような。 デザインパターンを学習されているなら継承を使う機会は減ると思うんですけど。 #減るというか注意深くなるというか >本は色々読みましたが、全てが同意できる物はありません。 となると、ここで力説されていらっしゃる実装継承を使ったOOP をどこから学ばれたのか興味深いですね。 ちなみにこのページはオブジェクト指向を学ぶうえにおいてとても参考になります。 一読してみてください。 http://d.hatena.ne.jp/sumim/20040525/p1
[この投稿を含むスレッドを表示] [この投稿を削除]
[1273] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/20 13:42:06

大文字小文字の例が悪かったのか、話がそこから進まないようです。 修正方法には以下の4つがあります。 ----------------------------------------------------------- 1.別名でメソッド追加  別々の処理として追加したい場合に使用 2.継承  関連処理をまとめて変更したい場合に使用 3.分割して親クラスを継承  関連処理をグループ化して、片方のグループを変更したい場合に使用 4.staticメソッドを作成  関連のない任意の場所で使用したい場合に使用 ----------------------------------------------------------- それぞれ用途が違いますが、オブジェクト指向特有で強力なのが2,3です。 別に全て2でやれと言っているわけではなく、2の使い方が出来るのが 利点だと言っている訳です。 間違いやすいとか分かりにくいと言うのは、実装者のスキルの話で、 よく見て追えば分かるし、変な設計をすれば分かりにくくなります。 遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 オブジェクト指向の場合は処理は関連するデータと共にクラスに まとめられるため、その引数を必要とするメソッドを、引数のクラス内 に実装できるか検討すべきです。 つまり、分かりやすいとか間違えやすいとか言う話は別として、 4種類の変更方法を選択できるため、再利用性が高いと言っている訳です。 >ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >でしょうか。 本は色々読みましたが、全てが同意できる物はありません。 殆どが、オブジェクト指向と言いつつ、デザインパターンの説明本や、UMLの説明本、 プログラミング言語の小技本、翻訳がおかしい本、中にはWEBアプリケーションの 作り方本もありました。 WEBサイトも同意できる物もあれば、出来ない物もあり、半々ぐらいです。 オブジェクト指向関係の書籍のひどさは、(ぱ)さんもご存じだと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1272] Re:疑い深い・・・
投稿者:774RR
2009/05/20 11:17:08

# 題名にハンドル入れるのやめてほしい > SE 氏 変えちゃいました # [1269] に返信してもよかったんだけどこっちにつなぐことにする [1269] > これを次のように変更します。1行で済みます。 ものすごく近視眼的コメントがついていて思わず苦笑してしまったのだけど、 *** そういう範囲でしか変更がありえない **** のであれば [1260] [1269] で提示のような修正もまぁあり、の範疇に収まります。 が、実世界においてはそういう局所な話ですまないことのほうが多く、 俺も (ぱ) 氏ももっとマクロな=大規模プログラムでの応用の話をしているわけです。 そういうレベルでは、提示のコードのような派生はうまくいきません。 そもそも OO (というか継承-派生というシステム) のおいしいところは ・「基底クラスを使う人」と「派生クラスを作る人」が分離できる ・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい ・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、  自動的に正しく使ってもらえる、と判断してよい という点にあるのであって、 決して「ソースの再利用のためのテクニック」ではないのです。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&thread=270 このへんとか。 基底クラスを使っている側にとって 基底クラス側が本来期待している挙動と異なる動きをするような派生クラス というのはまずいのです。 しかも、基底クラスユーザと派生クラス作者はたいてい別人なのです。 基底クラスを使うソースファイルと派生クラスを作るソースファイルも別ファイルなのです。 [あたかも便利そうに見える] [が、正しく設計されているとは必ずしも言い切れない] 派生クラスを安直に作り、使ってしまうと 異なる開発者がいて、複数のファイルから構成されていて、各プログラマは自分の担当範囲しか理解しきれない という大規模開発では見えにくい/直しにくいバグの元となります。 LSP (Liskov Substitution Principle) という概念も、この辺から来ています。 んで、マルチプルインスタンスの件のほうはもういいのでしょうか? 俺としては既に書いたとおり「対象読者層が異なる」というだけの話だと思っております。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1271] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/20 03:49:06

# どうもサーバの調子が悪いようで…… まず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さんはどんな本でオブジェクト指向の勉強をされたの >でしょうか。 これについては答えていただけないのでしょうか。ぜひ書名を教えて欲しいのですけれども。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1270] >(ぱ)こと管理人さん
投稿者:SE
2009/05/19 16:21:52

>まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は >ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて >いただきたいです。 「マルチプルインスタンスがオブジェクト指向」と言う論理です。 マルチプルインスタンスと言うのが何を指すのがよく分かりませんが、 状態(内部の変数の値)の違う複数の処理群(クラス)と解釈しました。 >そこでわざわざ継承してクラスを作ったって、以下のような問題が起きるだけです。 >・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのかわからなくて危険。 引数の型を見れば分かると思います。 >・別の誰かがLowerStackを作ったら、いつかマージするの? もし別機能として作るなら、Stackを継承してLowerStackを作ります。 例えば大文字にした後に先頭に0を付加するような、UpperStackの処理結果に追加する物なら、 UpperStackを継承して作ります。 すでにLowerStackが出来てしまっているならマージしません。 >「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >ということにしたいのでしょうか? そうです。 >この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 >「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる >既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 既存コードはソースに手を入れないので、影響はないと思いますが。 新たに作るコードはどちらを使うか意識する必要はありますが。 >上のほうで『実のところ「要素を大文字に変換して返すスタック」がどんな時に >役に立つのか想像できません』と書きましたが、結城浩さんが「例は嘘をつかない」 >と書いておられるように、こういうところで現実のプログラムに即した適切な例が >出てこないなら、おそらくそれは考え方のほうが間違っています。 もう少し分かりやすい例をあげます。 --------------------------------------------------------------------- Map<String, String> mp = new HashMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } --------------------------------------------------------------------- 入力した順番に表示したい場合 --------------------------------------------------------------------- Map<String, String> mp = new LinkedHashMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } --------------------------------------------------------------------- ソート表示したい場合 --------------------------------------------------------------------- Map<String, String> mp = new TreeMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } ---------------------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1269] >774RRさん
投稿者:SE
2009/05/19 15:22:44

>あえて言わせていただくと、提示例はやっちゃダメな「実装継承」の典型例であって >俺の後輩君がこんなコードかいてたら0点つけるですよ。 大文字変換は何かしらの処理の例として出したので、getで何かの処理を行った結果を返すと考えてください。 >これは、実体が Stack であるインスタンスに対して UpperStack にダウンキャストして使う、としか読めない。 >そんな危険なことをさせるわけにはいかないと思うのだが。 ダウンキャストでなく、newするときに新しいクラスを使うと考えてください。 --------------------------------------------------------------------- Stack st = new Stack(); st.put("aa"); st.put("bb"); st.put("cc"); System.out.println(st.get()); System.out.println(st.get()); System.out.println(st.get()); --------------------------------------------------------------------- これを次のように変更します。1行で済みます。 --------------------------------------------------------------------- UpperStack st = new UpperStack(); st.put("aa"); st.put("bb"); st.put("cc"); System.out.println(st.get()); System.out.println(st.get()); System.out.println(st.get()); ---------------------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1268] Re:状況その4
投稿者:
2009/05/18 20:59:24

Kmyaccを使用していましたが、エラー復帰がうまくいかず。1回の構文エラーで yaccが終了してしまう問題を抱えてしまいました。いろいろ調査したが、どう にも情報が見つからなかったため、Bisonに変更。問題なくエラー処理および エラー復帰が出来るようになりました。堅牢なシステムへまた1歩です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1267] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:
2009/05/18 18:28:11

>これなんですが、C++だと、privateなメンバ変数とかは、外から参照すれば >コンパイラにエラーで怒られるとはいうものの、.hファイル中には記述されて >しまいますよね。  カプセル化という言葉に対して、きっちりとした完全な意味を求めてるのだ ろうと思いますが、私はそこまでのことを意識してこの言葉を使っていません。 問題は。  必要なこと意外一切情報を出さないほうがいいのか。内部がある程度想像 できるほうがいいのか?Cはたとえ使えなくともクラスのデータやメソッドが見 える。これが良いか悪いかでしょう。私は後者のほうが気分的には良いです。 使わない情報が見えたとしても、実質的にカプセル化されていれば問題ないと 考えます。  言語の設計において、理想的なものを作っていくのもあります。私の場合は 目的が実現できれば簡単なものでいいと思って設計しています。その代表が #defineです。古い仕様で問題点も内包しますが、実に使いやすく融通が利きます。 今では#defineはあまり良くないとされていますが、私は利点を選びました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1266] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:(ぱ)こと管理人
2009/05/17 20:50:06

> 私にとってOOPを使う最大の理由は。 > > 「カプセル化により見透視のよさ!」これに尽きます。 これなんですが、C++だと、privateなメンバ変数とかは、外から参照すれば コンパイラにエラーで怒られるとはいうものの、.hファイル中には記述されて しまいますよね。Javaだとメソッドの実装も書くことになるのでもっと深刻です。 これでは利用者側の再コンパイルが必要になりますし、ライブラリの実装が 終わる前にアプリケーションを作り始めたいという場合にも困る、ということで、 (Javaで言えば)インタフェースのみ公開してHogeImplみたいなクラスを作る、 なんてパターンが知られています。 私にはこれは必須に思えるので、Diksamではもうちょっと言語で積極的に サポートしたかったんですけどね。うまい文法が思いつかずにJavaと同等に なってしまっています。うーん、いつかそのうち。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1265] Re:疑りぶかいあなたのための「オブジェクト指向再入門」を読んで
投稿者:(ぱ)こと管理人
2009/05/16 22:40:50

>その論理で行くと、マルチプロセスやマルチスレッドはオブジェクト指向になると >思いますが、 ならないと思いますが…… まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて いただきたいです。 >例えばこれを修正して、大文字に変換して返す物を使いたいとします。 >----------------------------------------------------------- >public class UpperStack extends Stack { >  public String get(){ >    return super.get().toUpperCase(); >  } >} >----------------------------------------------------------- 774RRさんがすでに書いていますけど、これは典型的な「ダメな実装継承の例」でしょう。 # 「実装継承」でGoogleしてみることをお勧めします。 実のところ「要素を大文字に変換して返すスタック」がどんな時に役に立つのか 想像できませんが、それはまあ、「あくまで例だから」ということにしても、 このケースは、 「要素をgetする側は、大文字が欲しいとき、そのことを意識している」 のでしょうか。 意識しているのであれば、そもそも「stack.get().toUpperCase();」で済む話です。 大文字に変換する、という単純な処理でないのなら、ユーティリティメソッドを 作ればよいでしょう。 そこでわざわざ継承してクラスを作ったって、以下のような問題が起きるだけです。 ・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのか  わからなくて危険。 ・別の誰かがLowerStackを作ったら、いつかマージするの? ・ユーティリティメソッドではprivateメンバにアクセスできないが、  継承なら、protectedにしておけばサブクラスからアクセスできる、というのが  趣旨なら、それはカプセル化の破壊以外の何者でもない。 ところで、SEさんの例では、get()メソッドがオーバーライドされています。 「要素をgetする側は、大文字が欲しいとき、そのことを意識している」のであれば、 仮に継承を使うとしても、getUpper()メソッドをつけることでしょう。 オーバーライドしているということは、 「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 ということにしたいのでしょうか? # それにしては、get(boolean up)と対比しているのでよくわかりませんが。 もしそうなら、 >そのため、変更により以前の機能のまま使用したい場所には影響がありません。 というわけにはいきません。 この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる 既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 しかも、get(boolean up)とは違い、実際に動かしてみなければ検出できない バグになりますからさらにタチが悪いです。 上のほうで『実のところ「要素を大文字に変換して返すスタック」がどんな時に 役に立つのか想像できません』と書きましたが、結城浩さんが「例は嘘をつかない」 と書いておられるように、こういうところで現実のプログラムに即した適切な例が 出てこないなら、おそらくそれは考え方のほうが間違っています。 ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの でしょうか。 いまどきこんなバリバリの実装継承でオブジェクト指向を説明している教科書は そうそうないと思っていたので、もし新しい本にそういうことが書いてあったのなら 興味があります。ぜひ書名を教えてください。 ところで、私が現在作っているクラスベースオブジェクト指向言語Diksamでは、 「concreteクラスは継承できない」ということにしてしまっています。これは 実装の手抜きではなく、意図して行っています。 ここまでやってしまうと異論はあるかもしれませんが、Effective Javaとか GoFのデザパタ本とかで、かなり昔から、散々「抽象クラス以外は継承するな」と 言われてますし、SEさんのような誤解を防止するためにもこの方がよいのではないかと。 http://java-house.jp/ml/archive/j-h-b/050862.html
[この投稿を含むスレッドを表示] [この投稿を削除]