トップページ⇒tech
1001コメント409KB

OOP 2

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2010/11/10(水) 22:51:25
前スレのあらすじ

OOPってよくわかんないよね

http://hibari.2ch.net/test/read.cgi/tech/1284115490/
0587デフォルトの名無しさん2010/12/02(木) 01:08:05
ソフト屋ですらない奴がソフト屋のコモンセンスを問うとか何のジョークですか?
0588デフォルトの名無しさん2010/12/02(木) 01:13:43
ん?マルチディスパッチは共通の基底クラスを必要としない点で、C++なんかの多態より疎結合だし、
オブジェクト指向って言うほど、オブジェクト中心の考え方でもないんだから、
「どうすれば」とか言われてもなぁ。普通に使うだけでしょ。
0589デフォルトの名無しさん2010/12/02(木) 01:19:52
>>588
>>526
0590デフォルトの名無しさん2010/12/02(木) 01:23:53
>>588
マルチディスパッチでは多態させるためにfunc1( oo, xx )シリーズが組み合わせ爆発でずらずらと並ぶ。
カプセル化による内部データ隠蔽があるのか無いのかはっきりしないが、
無いのだとすればどれか一つのデータ型の構造に変更が加わるだけで、
そのデータを引数に取るfunc1を全て改修しなければならない。

多態のメリットをまるごとつぶしてるようにしか見えない。
0591デフォルトの名無しさん2010/12/02(木) 01:25:46
>>586
歪んでるからな。一見簡単そうに見えるものほど実は複雑だったり。
簡単そうに見せてるだけって場合がほとんどだからな。
しかも簡単そうにみせるための仕組みで余計複雑怪奇になってたり。
だって、難しいものは簡単にはならんだろうよ。難しいものは難しいままで良いんだよ。
良くあるのは一部だけ見せるってやつな。最近のGUIで多いよね。メニューバー隠したり。
過去には1ボタンマウスってのがあったな。アレは最悪だった。
今はセンサーでやってるんだっけか。もっと最悪だな。何で隠すんだろうな。
とりあえずホイールは画期的だったね。

OOPで言えば、オブジェクトを前面に持ってきたってのがなぁ。
アイ何とかって感じだよな。
したたかにCにマルチメソッドでも実装してればよかったのに。
0592デフォルトの名無しさん2010/12/02(木) 01:33:47
>>573
C++が大変なことになってるのは一番最初から。
Cとの互換を目指したのがC++最大の間違い。
OOPLとしては最も腐ってるものを引き合いにして
OOPLを語られても困る。
0593デフォルトの名無しさん2010/12/02(木) 01:40:04
>>590
アクセサ通してアクセスすりゃいいじゃん。
単一ディスパッチで纏められる要求仕様なら、纏めればいいじゃん。
マルチメソッドは単一ディスパッチも出来るんだぜ。
ただ、マルチディスパッチと言う飛び道具もありますよってだけで。

マルチディスパッチ自体が重要なんじゃなくて、
マルチディスパッチをサポートすることで言語仕様に対称性がでることに意味がある。
たとえば、多態するのに共通の基底クラスが必要なくなったりする。
多態のことなんか何も考えてないCの構造体で多態できたりもする。
もちろん基本型でも多態出来る。凄く自然なんだよ。
そういう自然さが大事。
オブジェクトにvtable持たせたのが運のつきだね。
多態はポインタ越しにしか行わないんだから、
型情報はポインタに持たせれば良かったんだよ。ポインタががんばる。インスタンスは何もしない。
構造体→型持ちポインタ→マルチメソッド機構→Cスタイルの関数。
こんな単純な仕組みで良かったんだよ。継承とか要らなかったね。
0594デフォルトの名無しさん2010/12/02(木) 01:47:37
>>592
互換性なんて微塵も無いのにな。
だって、継承なしのCの構造体では多態できない。
オーバーロードは機能するがな。
マルチメソッドだと、継承なしのCの構造体でも多態できるし、vtableみたいなゴミも付かないし、
そっちのが互換性あったのにな。
システム増築するときって、元のシステムにはなるべく手を加えないようにするもんだろ。
何勝手に構造体にvtableとか追加してんだよ。
新しく、動的型持ちポインターとか増設して、そっちで多態なりなんなりすりゃよかったのにな。
その型持ちポインターからマルチメソッドのテーブル通してCの関数にリンクさせりゃ良かった話じゃねーか。
本当に、なんでああなったんだろうな。
0595デフォルトの名無しさん2010/12/02(木) 01:53:14
>>593
マルチディスパッチがあってもいい理由としては分かったが、
オブジェクトが要らない理由にはなってないよ。

アクセサ(というかアクセサはメソッドの役割のほんの一部だぞ)があっていいなら、
特定の関数群をオブジェクトという単位でまとめてはいけない理由は何?

『プログラムはデータとそれを操作する関数として記述されるべきであり、
「特定のデータに属する関数」という存在はナンセンスだ』というのが君の主張だったよね。

むしろ、あるオブジェクトの状態を操作する関数が一箇所に記述されていることが
言語として保証されていた方が、コーディングをする側としては見通しが良くなるよね。
「あるオブジェクトを操作するメソッドは、あるクラスの中に書かれている物以外に存在しない」
ということに確信が持てるからね。
0596デフォルトの名無しさん2010/12/02(木) 02:02:20
>>593
は?
C++でCスタイルの構造体に、vtableなんてついてないぞ?
クラスのスタイルで書いたら特殊なクラスになるだけだ。
0597デフォルトの名無しさん2010/12/02(木) 02:14:35
>特定の関数群をオブジェクトという単位でまとめてはいけない理由は何?
vtableを持つ羽目になるからだ。それでも動的型言語ならまだマシなんだが、
静的型言語だと継承しなきゃ多態できない。
しかもvtableを構築するためには継承しか手段がないから、
クラス設計者以外は多態のあり方を決めれない。
クラス設計者がインターフェースを決め打ちするわけだ。
よって利用者はインターフェースが気に入らなけりゃ、アダプタクラスを作る羽目になる。よくある光景。
初めから多態前提で設計しなきゃ多態出来ない。
でも、そのクラスがどう使われるかまでは、クラス設計者にはわからない。
クラス設計者は、クラスの内のことは解っても、外のことはまるで解らないだろうに。
なのにクラスの中で多態の仕組みを構築する。。おかしいだろ。
多態は、どう使われるかって言う、外の世界の影響を色濃く受けるのによ。
外の世界の都合で決まるものを、内で定義するのは変だと言って・・・あー眠たくて文章が支離滅裂気味
要は、多態は外でやれ。共通の基底クラスなんてもってのほか。

>むしろ、あるオブジェクトの状態を操作する関数が一箇所に記述されていることが
カプセル化はまた別の仕組みでやりゃ十分だと思うがね。
ネームスペース単位のカプセル化なんて勝手が良さそうに思うが。
クラス単位だけってのそれはそれでしんどいでしょ。
0598デフォルトの名無しさん2010/12/02(木) 02:18:40
>>596
構造体にvtableが有ったり無かったりする訳だよ。
まー別にC++のRTTI構造体がCのそれと同一である必要はまるで無いのだが、
同一でなくする必要もまた無かったんだよ。ポインタに型情報を持たせりゃそれで済んでた。
あえて違わす必要も無かっただろ。互換性重視っていうならなおさら。
Cの構造体で多態できるようにもなるしな。
0599デフォルトの名無しさん2010/12/02(木) 02:20:15
・classをやめてinterfaceにすれば疎結合になる
・interfaceにはフィールドがないのでprivateもprotectedも不要
・interfaceにはコンストラクタもデストラクタもない
まずは「classはせいぜいstructと同程度の価値しかない」ということを確認し
その後でマルチメソッドについて議論すればよいと思います
0600デフォルトの名無しさん2010/12/02(木) 02:26:42
マルチメソッドが有れば、インターフェースなんぞいらん。
名前が同じ関数は、全て同じインターフェースだ。
ひとたび呼び出せば引数の型に応じて正しくディスパッチされる。
ただそれだけ。
0601デフォルトの名無しさん2010/12/02(木) 02:30:38
>>597
君が今言ったそれをひっくり返すと、それがそのままオブジェクト指向で書くことの
メリットになるってことには気付かないかな。

> クラス設計者がインターフェースを決め打ちするわけだ。
> クラス設計者は、クラスの内のことは解っても、外のことはまるで解らないだろうに。

だからこそ、オブジェクト間の疎結合が実現できる。
それが、オブジェクトの外側に対して一切責務を持たず、インタフェースが固定されていることの恩恵だ。

多態は、無理に使う必要は全くない。
よくあるパターンは、インタフェースである HogeService と、唯一の実装クラスの HogeServiceImpl だな。
んで、単体テスト時に、HogeServiceImpl の代わりにモッククラスの HogeServiceMock を使うことで
テスト容易性を高めることができる。

> よって利用者はインターフェースが気に入らなけりゃ、アダプタクラスを作る羽目になる。

いいんだよ、それで。無理に丸のまま再利用する必要なんかない。
0602デフォルトの名無しさん2010/12/02(木) 02:32:59
>>600
少なくとも、オブジェクト指向の文脈ではそれをインタフェースとは呼ばんよ。
0603デフォルトの名無しさん2010/12/02(木) 02:34:27
interfaceでない引数はディスパッチと無関係ということにすれば
組み合わせが多すぎるという問題が起きにくいと思います
0604デフォルトの名無しさん2010/12/02(木) 02:35:40
>>603
んなこたなぁない。
0605デフォルトの名無しさん2010/12/02(木) 03:06:41
>>519
Rubyのハッシュを使って関数を実行するとこんな感じになるね。

def func1
  print "hello"
end

x = { "hello" => func1 }
x["hello"]       # これでfunc1()を実行したことになる

クラスをまるごとハッシュに入れることも可能。

class FuncClass
  def func1
    print "hello"
  end
end

func_obj = FuncClass.new
x = { "hello" => func_obj }
x["hello"].func1()
0606デフォルトの名無しさん2010/12/02(木) 03:12:58
func(obj1, obj2)ってやっぱりわかりにくいだろ。
funcにobj1,obj2を渡して、それがどう処理されて、どういう結果になるのか仕様書見ないとわからない。
戻り値があるのかないのか、エラーはどこに返されるのか、結果はobj1,obj2に入って返されるのか、
それとも左辺に出てくるのか、どういう形式で返ってくるのかなどいろいろ調べなきゃならない。

obj.method(obj2);なら、objオブジェクトがどういうことをするオブジェクトかが大体わかっていれば、
そのオブジェクトにmethodというメッセージを投げているのはすぐわかるし、
そのmethodを実行させるためにobj2が必要なんだなということまではわかる。
他人が書いたソースを読むときの読みやすさが全然違うと思うんだけど、どうよ。

マルチメソッド使わせたいなら、どれだけ簡単に書けて、どれだけコードが読みやすくなるかという
メリットを示さないと広く使われることはないだろうな。
0607デフォルトの名無しさん2010/12/02(木) 09:41:24
流れ読んでないが、一言。

両方の型でポリモしたいようなときはobj.method(obj2);じゃ正直まんどいよな。
だからダブルディスパッチに、苦肉の策でVisitorパターンなんか使うわけで。

A, B, C, D, Eクラスがあって相互に衝突検出を使用とした時とか。
そこに追加でFクラスが来たとき、全部のクラスに追記が必要だし、
AとBの衝突を「どっちに書くのか?」という問題もあり、
A.衝突(B)とB.衝突(A)に矛盾がないようにしようとするなら、
互いに実装について申し合わせてないといけない? これはなんとかなる?

Visitorパターン使ったとしても、やったことあるやつなら分かるが煩雑。
あーしてこーしてこう。そんなんするくらいならマルチメソッドとやらで、
衝突(A, B)と書かせてもらうほうがよっぽどラク。よっぽど自然。

これは、ダブルディスパッチせざるを得ない状況が設計として悪いのか、
どうなのか、ちょっと先に考えてみたい気もするが。
0608デフォルトの名無しさん2010/12/02(木) 11:53:58
>>607
衝突(a,b)なら

interface 衝突インターフェース {
  衝突する(<衝突インターフェース> 対象)
  衝突される(<衝突インターフェース> 何に衝突されたか)

  // その他、衝突処理内での通信に使うメソッドをいくつか
}

んで、A〜Eクラスは衝突インターフェースを実装。
衝突(obj) は内部で必ず obj.衝突される(self) を呼び出すものとする。

これでお互いのオブジェクトを参照可能になるので、あとはお互いの衝突処理をする。
どっちに書く、ではなく、どっちも自分についてのみ書く。
相手に何かして欲しいなら、インターフェースに書かれたメソッドを使って「○○して」と頼む。
0609デフォルトの名無しさん2010/12/02(木) 12:02:02
ところで、自分で書いてて思ったんだがこれって何てパターンになるの?
OOPLはよく使うけど、デザパタは良く知らんのだが。
0610デフォルトの名無しさん2010/12/02(木) 12:14:45
カプセル化による共通インターフェースの提供を否定するダブルディスパッチは多態じゃないから。
引数をvoid*で受けてRTTIかその他の識別コートを解析して処理を決定するのと大差ない。
文法定義が関数定義に置き換わったパーサと同義。

その上で「じゃあ多態じゃなくてもいいや」というのは至極真っ当な判断。多態に拘る必要は無い。
0611デフォルトの名無しさん2010/12/02(木) 13:09:19
オブジェクトa, bの衝突を判定する責任を負うのは誰か?と聞かれたらa, bのコレクション(あるいはその所有者)になると思う。
コレクション.衝突判定() みたいなのがあって、その中で全オブジェクトの衝突を判定するわけ。
a,bを含む各オブジェクトは位置、形状、サイズなど、衝突判定に必要な情報を持たないといけない。
その条件付けを決めるのがインターフェースや基底クラスの役割。

その上で、矩形同士、円と円、円と矩形など、特定の矩形の組み合わせの場合に計算を簡素化(最適化?)できる場合がある。
この時、無理に共通インターフェースと称して各図形をポリゴンや矩形の組み合わせなどで近似したり、
形状ごとにifやcaseで分岐するよりも
マルチメソッドを使って場合分けすればシンプルに記述できるのではないか。

interface 形状 {};
class 円 implements 形状 { 中心 x,y; 半径 r;};
class 矩形 implements 形状 { 幅 w, 高さ h; };

interface 星 { 形状 getShape(); }

class コレクション {
 星 hoshi[];
 衝突判定() {
  for (int i=0; i<hoshi.length()-1; i++) {
   if (衝突判定(hoshi[i].getShape(), hoshi[i+1].getShape())) { /*衝突してたときの処理/* }
  }
 }
 衝突判定(円, 円) { /*円同士の衝突判定*/ }
 衝突判定(円, 矩形) { /*円と矩形の衝突判定*/ }
 衝突判定(矩形, 円) { /*矩形と円の衝突判定*/ }
 衝突判定(矩形, 矩形) { /*円同士の衝突判定*/ }
}
0612デフォルトの名無しさん2010/12/02(木) 13:25:11
>>611
横からだが。

if (衝突判定(hoshi[i].getShape(), hoshi[i+1].getShape()))
↑これじゃあ狙い通りにディスパッチできないよね?

 衝突判定(形状, 形状)
を↓に割り振る仕組みが、Visitorパターンだったりする。

 衝突判定(円, 円) { /*円同士の衝突判定*/ }
 衝突判定(円, 矩形) { /*円と矩形の衝突判定*/ }
 衝突判定(矩形, 円) { /*矩形と円の衝突判定*/ }
 衝突判定(矩形, 矩形) { /*円同士の衝突判定*/ }

だから、ディスパッチするだけで不毛なステップを要する。
0613デフォルトの名無しさん2010/12/02(木) 14:10:08
>>611
> 衝突判定() {
>  for (int i=0; i<hoshi.length()-1; i++) {
>   if (衝突判定(hoshi[i].getShape(), hoshi[i+1].getShape())) { /*衝突してたときの処理/* }
>  }
> }
上記を下に訂正^ ^;

 衝突判定() {
  for (int i=0; i<hoshi.length()-1; i++) {
   for (int k=i+1; k<hoshi.length(); k++) {
    if (衝突判定(hoshi[i].getShape(), hoshi[k].getShape())) { /*衝突してたときの処理/* }
   }
  }

>>612
>if (衝突判定(hoshi[i].getShape(), hoshi[i+1].getShape()))
>↑これじゃあ狙い通りにディスパッチできないよね?
多重ディスパッチをサポートしてる言語のつもりで書いたんだけど、それでもだめかな?
0614デフォルトの名無しさん2010/12/02(木) 14:16:21
> 多重ディスパッチをサポートしてる言語のつもりで書いたんだけど

おk把握。
0615デフォルトの名無しさん2010/12/02(木) 20:09:55
OOP + マルチメソッド が最強ということだな
0616デフォルトの名無しさん2010/12/02(木) 20:31:19
>>607
その例は、マルチディスパッチが必要とされる場面の代表的な例だね。
そういうコーディングが必要な場面はあるにはある。

けど、そこからオブジェクト指向は云々というのは論理の飛躍と言わざるを得ない。
だって、A, B, C, ...がオブジェクト指向的に作られていることと、マルチディスパッチは矛盾しないから。

いつもの人の主張は、A, B, C, ...の内部状態の操作は、個別のオブジェクトに属させず全て衝突()に書くべき、
というもので、それが疎結合の実現という観点から言って問題がある、という点は既に指摘した通り。

また、衝突()でA, B, C, ...を操作する際に各オブジェクト専用に定義したアクセサ関数を経由するようにするなら、
なおさら、オブジェクトにメソッドを属させるというコンセプトや、カプセル化といった便利な機能を手放す理由はない。
静的型言語なら、形式的なルールをコンパイラが静的にチェックしてくれるというメリットまでついてくるのだからなおさら。
0617デフォルトの名無しさん2010/12/02(木) 21:22:10
マルチメソッド編はこれにて一件落着だな

次はダックタイピングか?
0618デフォルトの名無しさん2010/12/02(木) 22:04:56
次はVisitorパターンだ。

Visitorパターンの主張は、
obj.accept(visitor);
objに属するメソッドはaccept()だけで他は全てVisitorとして独立するべき、
というものだ。
0619デフォルトの名無しさん2010/12/02(木) 22:44:28
マルチディスパッチの代用品だし、そんなに積極的に使うべきパターンというわけでもない。
とりあえずメリットを言うなら、「データからアルゴリズムを分離し、新たな操作の追加が容易になる」こと。
0620デフォルトの名無しさん2010/12/02(木) 23:16:54
>いつもの人の主張は、A, B, C, ...の内部状態の操作は、個別のオブジェクトに属させず全て衝突()に書くべき、
何でそうなるんだよ。衝突判定の関数の中から、別の関数を呼んでも良いし、
その別の関数とやらが、多態性を持っていたってかまわないし。要は自由なんだよ。
結合度は書く人次第だよ。
単一ディスパッチで出来ることは、マルチメソッドでも出来る。
マルチメソッドで出来ないことは単一ディスパッチにも出来ない。
結合度についても同じなんだ。
単一ディスパッチの方が結合度が下がる仕様条件なら、単一ディスパッチですれば良い。
マルチメソッドは単一ディスパッチもサポートしてるんだからな。
0621デフォルトの名無しさん2010/12/02(木) 23:35:30
でさ、マルチメソッドは言語の対称性があがって綺麗になるが、
そんなに出番は無いだろう。基底クラスを持たなくても良いから、その分楽になるってのはあるが。

いつも何か思いつく俺だけど、今度はGCについて思いついた。
メモリを勝手に管理してくれるのはいいが、OSのリソースの面倒までは見てくれない。
仕方ないからメモリに括り付けて、CG発動時に開放されるようにプロシージャを仕込んどく。
だけど結局いつGCが発動するか解らないから、結局こまめに手動で開放したりする。
でもさ、俺おもうんよ。面倒見れないんだったら、初めからノータッチでいいだろ。

メモリブロックの種類を2種類に分ければいい。
メモリのみのリソースを含むものと、メモリ以外のリソースを含むものに。
前者はメモリしかリソースを含まないって言ってんだから、CGで回収すりゃいいし、その際、開放関数をコール必要も無い。
後者はメモリ以外のリソースも含むのだから、CGでは回収しない。手動で開放する。
しかし、マーキングは行い、メモリリークを検出する。ログかなんかに吐き出す。
何処からも辿れないメモリ断片があるぞ。開放忘れてんじゃねーかって。

マークアンドスイープnew、マークnew、普通のnew、と言う風に、newのバリエーションが3種類になる。
ちょっと煩雑すぎるかネェ。
0622デフォルトの名無しさん2010/12/02(木) 23:36:39
>>620
多態を使うか使わないか、単一ディスパッチかマルチディスパッチかは、
結合度の話とは関係ないのだが。

マルチディスパッチを使うと結合度が上がるんじゃなくて、複数のオブジェクトの状態を
一つの関数内で同時に操作しようとすると結合度が上がる、という話。
0623デフォルトの名無しさん2010/12/02(木) 23:38:58
ところで、>>601は理解できたかね。
0624デフォルトの名無しさん2010/12/02(木) 23:42:01
>>620
自由自由というけど、どのくらいの規模のソフトを
何人ぐらいで作るのを想定しとんの?
0625デフォルトの名無しさん2010/12/02(木) 23:50:46
>複数のオブジェクトの状態を
>一つの関数内で同時に操作しようとすると結合度が上がる

それは、そのプログラムの要求仕様から導き出された設計仕様だろ。
要求仕様が複雑だと、設計仕様も複雑になるっていってるようなものだ。
何も言ってないんだよ、お前は。
マルチメソッドも、OOPも、何もかも関係ない。
>>526をよく読み返してみ。支離滅裂だろ。

>「マルチディスパッチがあれば、オブジェクト指向を置き換えられる」という発想がおかしいんだな。
>これらの関数は、どう逆立ちしたって a_t や b_t に密結合したものにならざるを得ない。

とお前は言うが、その例だと、マルチディスパッチが無い場合でも、密結合になるだろう。
何の証明にもなってない。
マルチディスパッチでも密結合。単一ディスパッチでもOOPでもCでも密結合。なんも変わらん。
0626デフォルトの名無しさん2010/12/02(木) 23:59:40
人間の思考って過去の経験を肯定するほうを選択するよね。
だから何を言ってるかより誰が言ってるかのほうが重要。
0627デフォルトの名無しさん2010/12/03(金) 00:11:08
>>625
> それは、そのプログラムの要求仕様から導き出された設計仕様だろ。

要求仕様を「素直に」実装すると密結合になるなら、疎結合になるように設計を変えればいいじゃない。
0628デフォルトの名無しさん2010/12/03(金) 00:14:00
単一ディスパッチはレキシカルスコープの代用品だ。
だから設計思想的に安定している面もあるが、
単なる代用品を超えて「過去の経験」を打ち破ってほしい面もある。
0629デフォルトの名無しさん2010/12/03(金) 00:15:19
どう言えば彼は納得するんだろうな。
彼の言ってることは、
「複数の引数を取る関数は、その引数について密結合になる」ってことでしょ。
でも、それは、マルチメソッドとは関係が無いよね。
そもそも、マルチメソッドは呼び出しの方式だから、ディスパッチ先の関数の結合度には関与しない。

なんつーかさ。仮に
int func( a_t a, b_t b)って関数があったとする。これは、引数のa_tとb_tについて、密結合だったとする。
この関数を呼び出す方式が、マルチメソッドだろうが、単一ディスパッチだろうが、静的呼び出しだろうが、
この関数自体の密結合には関係が無いよね。あくまで呼び出し方式の違いなんだから。
どう呼び出そうが、ディスパッチ先の関数の結合度は変わらないよ。

どういえば伝わるんだろうね。無理かもね。
0630デフォルトの名無しさん2010/12/03(金) 00:18:39
>>672
で、その疎結合になった設計は、
マルチメソッドを実装した言語でも記述できるんだろ?

だとえば、インターフェースそろえて単一ディスパッチに正規化しましたってんなら、
それでいいじゃない。マルチメソッドは単一ディスパッチもサポートするんだから。
マルチメソッドは、OOPの置き換えにならないってことにはならないだろ。
含まれてるんだから。
0631デフォルトの名無しさん2010/12/03(金) 00:24:20
>>630
>>616
0632デフォルトの名無しさん2010/12/03(金) 00:29:37
アンカー振られても反論としての意味がわからない。
0633デフォルトの名無しさん2010/12/03(金) 00:33:54
>>632
>>616
> だって、A, B, C, ...がオブジェクト指向的に作られていることと、マルチディスパッチは矛盾しないから。

> いつもの人の主張は、A, B, C, ...の内部状態の操作は、個別のオブジェクトに属させず全て衝突()に書くべき、
> というもので、それが疎結合の実現という観点から言って問題がある、という点は既に指摘した通り。

> また、衝突()でA, B, C, ...を操作する際に各オブジェクト専用に定義したアクセサ関数を経由するようにするなら、
> なおさら、オブジェクトにメソッドを属させるというコンセプトや、カプセル化といった便利な機能を手放す理由はない。
0634デフォルトの名無しさん2010/12/03(金) 00:38:40
>手放す理由は無い
マルチメソッドがOOPの置き換えになるって、もう自分で気づいてるじゃねーか。
理由は無いってだけで、「出来る」んだろ?
置き換えになるじゃねーか。
0635デフォルトの名無しさん2010/12/03(金) 00:40:19
> いつもの人の主張は、A, B, C, ...の内部状態の操作は、個別のオブジェクトに属させず全て衝突()に書くべき、

こんなことも言ってないしね。
それもかなり初期の段階でコードまで書いて示してる。
>>528でな。
0636デフォルトの名無しさん2010/12/03(金) 00:45:26
そもそも、君がマルチメソッドマルチメソッド言い出したのはそれをやるためだったと
記憶しているのだが、忘れたか趣旨替えしたのなら、まぁいいや。

んで、互いに置き換え可能(?)な構文を作るのはいいんだが、
ところで、オブジェクト指向で書くとダメな理由はどこへ行ったの?
0637デフォルトの名無しさん2010/12/03(金) 00:50:08
>そもそも、君がマルチメソッドマルチメソッド言い出したのはそれをやるためだったと
どこで書いた?単一ディスパッチを使うことを否定した覚えは無いが。
マルチディスパッチが出来ないことや、vtableの方式を否定しただけで。
0638デフォルトの名無しさん2010/12/03(金) 00:51:21
マルチディスパッチって
宣言型プログラミングの場合はどういうことになるんだろう・・・
0639デフォルトの名無しさん2010/12/03(金) 00:52:44
静的オーバーロード扱いになるんじゃない?ちょっと良くわからんが。
0640デフォルトの名無しさん2010/12/03(金) 03:43:35
マルチメソッドの話はもう飽きたし、俺は使わないから他の話にしてくれないかな。
マルチメソッド使いたい人は自分だけ使ってればいいだろ。
0641デフォルトの名無しさん2010/12/03(金) 06:53:30
>>634
横から

曲解しすぎだろ
「便利な機能を手放す理由はない」がなんで「置き換え可能」になるんだよ

あと単一ディスパッチとOOPを等号で結ぶのもやめてくれ
単一ディスパッチは多重ディスパッチで置き換え可能
と
OOPはマルチメソッドで置き換え可能
は別物だろ
0642デフォルトの名無しさん2010/12/03(金) 07:55:37
>>637
> そもそも、君がマルチメソッドマルチメソッド言い出したのはそれをやるためだったと

「それ」=obj1.func(obj2)という記法は誤りで、func(obj1, obj2)が正しいということを正当化すること
な。
0643デフォルトの名無しさん2010/12/03(金) 09:44:35
それオブジェクト指向となんか関係あんの?
0644デフォルトの名無しさん2010/12/03(金) 11:18:25
無いだろうね
記法は記法でしかなく、仕組みでもないんだし
0645デフォルトの名無しさん2010/12/03(金) 11:35:22
記法は実はもっとOOPらしさに関わってるような気もする。

cat foo | grep bar | sort | uniq

uniq(sort(grep(cat(foo), bar)))

cat foo.grep(bar).sort.uniq

メソッドの連結が思考の流れと近いのが好ましいのかもしれない。
0646デフォルトの名無しさん2010/12/03(金) 11:44:24
とはいえ、非OOPLでも命令や手続きを後置する言語あるのがなあ
FORTHなんかがそうだし、日本語プログラミング言語とかには割と多い
逆に、OOPシステムでありながら前置するCLOSとかもあるし
0647デフォルトの名無しさん2010/12/03(金) 11:45:40
指向の流れに一番近いのは手書きイラストだろ常考
0648デフォルトの名無しさん2010/12/03(金) 11:48:49
手書きイラストで何をどないせーっちゅーねんw
0649デフォルトの名無しさん2010/12/03(金) 11:50:35
FORTHやMIND(やPostScript)は前置後置というよりスタックマシンが生で見えてるだけだろ。
0650デフォルトの名無しさん2010/12/03(金) 11:52:11
"foobarbaz"

sb // string buffer

append(append(append(sb, "foo"), "bar"), "baz")

sb.append("foo"),append("bar").append("baz")
0651デフォルトの名無しさん2010/12/03(金) 11:55:01
>>648
画面にファイルのアイコンとディスプレイのアイコン書いて
フリーハンドの線で矢印ひいたら矢印の向きにデータ転送が行われるとか
0652デフォルトの名無しさん2010/12/03(金) 12:38:56
それってポリモーできないんじゃない?
0653デフォルトの名無しさん2010/12/03(金) 12:57:44
前置後置はさておき

>>630
操作の主体たるオブジェクトを特別扱いするのはOODの根本で、
あるオブジェクトを特別扱いすることが出来ないのは
OODによる設計を実装する言語としては二流。

OO開発手法を否定するならともかく、
いつもの言語はOOPLの変わりにはなれない。


あとマルチメソッドは言語機能でOOPは実装手法なんだから
比べるのは無意味で置き換えもクソもない。
0654デフォルトの名無しさん2010/12/03(金) 13:39:14
人月の神話を実現する言語としては。
0655デフォルトの名無しさん2010/12/03(金) 13:53:09
「え、神話?」
「はい。神話です。敵全員に大ダメージを与えます。」
0656デフォルトの名無しさん2010/12/03(金) 14:20:56
人月の神話、っつって話が通らないような会社からは全力で逃げるべきだなJK
0657デフォルトの名無しさん2010/12/03(金) 19:26:44
いまごろこのスレ知ったので前スレのログがあればだれかupしてくれぬだろうか?
0658デフォルトの名無しさん2010/12/03(金) 19:41:36
価値があるのかは分からないが
ttp://www1.axfc.net/uploader/Sc/so/179818.7z

DLキーはスレタイの頭3文字
0659デフォルトの名無しさん2010/12/03(金) 20:11:36
カプセル化が変数を隠蔽するだけでも相当美味しいと思うけどな。
構造体を第一引数に渡してOOPと同等のことができる〜みたいな論調もたまに見るが、
アクセスできない、とアクセスしなければ同等、とには無限の隔たりがある。
前者はそれを前提に、次のステップへ思考を移すことが出来る。
0660デフォルトの名無しさん2010/12/03(金) 20:20:02
>>659
何で晒してはいけないのかい?晒
0661デフォルトの名無しさん2010/12/03(金) 23:26:48
カプセル化すると内部データ構造を後から簡単に変更できる場合がある。
やっぱ配列やめて連結リストにしようか、とか。
0662デフォルトの名無しさん2010/12/04(土) 00:55:04
>>660
インタフェースと実装を分ければ、インタフェースが外部に対して約束している挙動を実現している限り、
実装を自由に変えることができる。リスコフの置換原則、でググってみるといい。

また、言語処理系がカプセル化をサポートしていれば、上記のことを確実に保証できる。
「プログラマが気をつければ問題ない」と思うかもしれないが、バグの多くは、
プログラマのちょっとした勘違いや、プログラマ同士のコミュニケーション齟齬によって生まれている。

機械的な方法を導入すれば、こうしたヒューマンエラーに基づくバグを根絶できるのだから、
積極的に導入しない理由がない。
0663デフォルトの名無しさん2010/12/04(土) 04:07:06
>>659

foo-private.h
#include "foo.h"

struct foo {
int foo1;
char foo2;
...
};

foo.h
typedef struct foo *foo_t;

int get_foo1(foo_t bar);
void set_foo1(foo_t bar, int baz);
char get_foo2(foo_t bar);
void set_foo2(foo_t bar, char baz);
...

とかやっておいて, foo-private.h を使用者側に公開しなきゃええんちゃう?

# そうゆう問題とちゃってたらごめん
0664デフォルトの名無しさん2010/12/04(土) 07:19:25
>>662
カプセル化のコストとしてはどんなことを計量すればよいのでしょうか?
0665デフォルトの名無しさん2010/12/04(土) 11:14:28
スコープってあるじゃん。
なんで全部グローバル変数にしないかっていうと、
あるいはなぜグローバル変数を消極的に使うかっていうと、
プログラム全体に変数が散らばっていくのを避けるためだ。
頭が超良くて、どんなに複雑でも瞬時に理解できるノイマンみたいなやつだと、
グローバル変数多用しても、実は問題ないのかもしれない。
しかし脳が非力な一般人はそうはいかない。できるだけ複雑にしたくない。
変数がプログラム全体に晒されるようなこともしたくない。

OOP、ここで特にクラスベースのそれでは、privateなメンバ変数は、
クラスの中だけに隠しておくことができる。アクセスは局所化しうる。
従来のスコープという概念に加え、クラスの内外というレベルでの制限ができる。

とくに生存期間が中期、長期のものは、それが生きている間、
いろんな場所を渡り歩く間、ずっと隠されるメリットは大きい。
もしこれが丸出しだったら、デバッグ時、渡り歩く箇所全部がデバッグ対象となる。

変数が小さくアクセスされるようにするのが正義。
カプセル化のおいしさも、結局そこにあるんじゃないか。
0666デフォルトの名無しさん2010/12/04(土) 11:51:08
>>665
変数を隠すのはいいんだが
変数を包む型や変数を初期化するコンストラクタを隠さなくていいのか?
0667デフォルトの名無しさん2010/12/04(土) 12:16:00
>>663
概ね正解(*foo_tの宣言時にfooって居なくていいんだっけ?)。
けど、言語処理系のサポートがあれば、もっと簡潔かつ柔軟に記述できる。

例えば、この場合はfoo-private.hを他のプログラマに渡すか渡さないかで制御しているわけだが、
オブジェクト指向言語なら、一つのクラス/オブジェクトに全てを記述できるので見通しが良くなるし、
protectedみたいな芸当もできる。
0668デフォルトの名無しさん2010/12/04(土) 12:33:41
>>664
外部に公開するインタフェースを吟味するコストとか?

>>666
依存性注入(DI)だな。そういうフレームワークは存在する。
利用者はインタフェース型だけ利用でき、インスタンスはDIフレームワークから受け取るのみとする。
実装型の知識やオブジェクトのインスタンス化は、全てDIフレームワーク側に設定ファイルとして持たせる。
0669デフォルトの名無しさん2010/12/04(土) 13:22:36
>>667
言語処理系のサポートがあった方がいいのは確かだけど
オブジェクト指向かどうかはあまり関係ないよな
0670デフォルトの名無しさん2010/12/04(土) 13:37:27
>>669
オブジェクト指向プログラミングの道具立てである個々の要素技術は、
オブジェクト指向に特有の概念ではない、という意味ではそうだね。

プログラムをオブジェクトという単位で考え、それを組み合わせて構成することで、
疎結合を実現する概念のことを「オブジェクト指向」と呼んでいるだけの話。

そして、オブジェクト指向でのコーディングをサポートするオブジェクト指向言語には、
多くの場合、カプセル化などの機能が備わっている。
0671デフォルトの名無しさん2010/12/04(土) 15:16:01
>>670
オブジェクト単位ならば疎結合で、メソッド単位ならば密結合ってことかな?

この主張がさんざん物議を醸していたわけだが
0672デフォルトの名無しさん2010/12/04(土) 15:49:22
>>671
メソッド単位じゃなくてモジュール単位だな。

で、俺も>>670の疎結合という言葉に引っかかる。
>>526からずっとおかしいし、疎結合の意味を取り違えているかOOに偏狭しているように思える。
0673デフォルトの名無しさん2010/12/04(土) 18:49:43
>>671
オブジェクト単位といってもオブジェクト間のやり取りはメソッドでやるんだから
その比較はあまり意味がないのでは?
0674デフォルトの名無しさん2010/12/04(土) 20:24:58
>>673
継承のことを言ってんじゃないか?

それにしても継承の事はあまり話題に上がらないよね
このスレ
0675デフォルトの名無しさん2010/12/04(土) 20:29:32
実装はクラス単位
やり取り=インタフェースはメソッド単位
「結合」に関与するのは実装ではなくインタフェース

クラスとインタフェースは類義語ではなくてむしろ反意語
だからクラス寄りのOOPとインタフェース寄りのOOPがある

この比較は意味がある
0676デフォルトの名無しさん2010/12/04(土) 20:36:19
また頓珍漢な説がでてきたな…
0677デフォルトの名無しさん2010/12/04(土) 21:03:48
前にも言ったことだが
OOPが頓珍漢なのは今に始まったことではない
それと、そうやって確信的に頓珍漢だと断定するのは形容矛盾だ
0678デフォルトの名無しさん2010/12/04(土) 22:01:52
>>671
既に指摘されてるけど、メソッドは対称となる概念ではないかな。
あえてメソッドに絡めて言うなら、あるオブジェクトの実装が、他のオブジェクトの
メソッド「のシグネチャ」にのみ依存しているなら疎結合だし、
メソッド「の実装」に依存しているなら密結合、ということになる。

>>672
確かにあまり厳密な使い方はしてないけど、一般的な用法からそんなに外れてないと思うよ。
早い話が、一方の実装が他方の実装に依存してない状態を指して言っている<疎結合。
このとき、一方に手を加えたり別の実装と取り替えたりしても、他方は一切変更する必要がない。

>>676
JavaやC#みたいなinterfaceキーワードがあるオブジェクト指向言語なら、
実質的には「クラス=実装クラス」として使われるから、そういう意味なんじゃない。

『インタフェースに対してプログラミングせよ、実装に対してプログラミングすべきでない』
0679デフォルトの名無しさん2010/12/04(土) 22:02:37
まーた始まった
0680デフォルトの名無しさん2010/12/04(土) 22:29:01
>>678
相変わらず>>526の意味が分からない。なぜ関数形式にすると密結合になるのか。
関数形式でもモジュール単位でアクセス制御すれば、OOと同程度に疎結合にできるはず。
>>671が指摘したかったのもその辺りのことなんじゃないかと思って672を書いた。

>>675に関しては中2行が酷過ぎて話にならない。
0681デフォルトの名無しさん2010/12/04(土) 22:29:45
>>678は至極まっとうな事に聞こえるけど?
0682デフォルトの名無しさん2010/12/04(土) 22:33:10
>>680
>>616で説明になってる?
0683デフォルトの名無しさん2010/12/04(土) 22:36:49
>>681
もうちょい具体的に書けよ

>>682
なってないし、どの部分が説明になっていると考えたのかも分からない。
0684デフォルトの名無しさん2010/12/04(土) 22:42:38
>>683
アンカーはしょったのが悪かったな
681は>>679宛てだ。レスが間に挟まっただけ
679が君の発言じゃなければ特に関係なし。
0685デフォルトの名無しさん2010/12/04(土) 22:43:53
>>680
非公開であると宣言するクラスと、宣言したものは素直に公開するインタフェース
どっちが酷いだろうか
0686デフォルトの名無しさん2010/12/04(土) 22:44:32
>>683
>>526は一般論として「関数形式にすると密結合になる」と言いたかったのではなくて、
>>616の後半で書いた通り、いつもの人の(以前の?)主張に対する反論として書いたものなので。
正直、彼はモジュール単位でアクセス制御するという発想があるかも怪しいし。
■ このスレッドは過去ログ倉庫に格納されています