掲示板
Powered by OTD
この記事は、K.Maebashi's BBSの過去ログです。
書き込む場合は、新しい掲示板へお願いします。
[日付順表示] | [日付順インデックス] | [スレッド順インデックス]


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


[360] Re:マルチプルインスタンス
返信


投稿者: うちゃ
2003/09/19 14:53

Mail:   Link:
 dentomさん、本多さん 横レス失礼します。

> aObjがmyUndoManager(型?インスタンス?)で作成されたobjectには、
> setFontというmethodは持ってない(らしい)が、
> aObjに対するsetFontというmessage送信に対して、
> どこかのobject(drawObject?)用のmethodを借りてきて(?)使うって感じなのかなぁ?
> #どのobjectがどんなmethodを抱えているのか知らないから余計ついていけない

 ”メッセージ”よりの説明すると、UndoManagerがsetFontというメッセージを預かって
おいて、実際のUndoが行われたときに、aObjに対して預かっていたメッセージを送る。
ということになります。

 関数呼び出しでの説明は、うまくできないのですが、UndoManagerはaObjのメソッドを知
ろうとしませんから、借りてきて使うという感じではありません。

> 呼ばれない「本来のsetFont」っていうのがどこのobjectのmethodを指しているのか
> 最終的に呼び出されるmethodはどのobject用に実装されたものなのか、
> aObjに対してそのmethodが正しい操作が行われることは、どうやって保障してるのか、
> drawObjectの実装を知らないとして、どんなobjectに対して正しく動作するのは
> どうやってわかるのか(myUndoManager class(?)のsuper classのどこかに
> drawObjectが含まれているのかとか?)

 こういうところが動的束縛のおもしろいところなのですが、aObjにどんなメソッドが
あるかとか、送られたメッセージを正しく解釈できるのかとかは、UndoManagerは関知し
ません。知っているのはコードを書いた人だけです。
 あらかじめ知らせておく必要がないため(Undoで行う操作の全てをUndoManagerに教えて
おく必要がない)UndoManagerに登録できるObjectにもMessageにも制限がありません。
 これを自由でやりやすいと見るか、いいかげんで信用できないと見るかで評価が分かれる
ところなんでしょう(^^;

> ついでに ここらへんも。Cだろうが何だろうが
> 1回も発生してないevent(undo)に対して関数呼び出しは発生しないと思うんですけど、
> 文脈的にそういう意味で言ったんじゃないんでしょう。
> methodへのlinkが呼び出されるまで形成されないっていう意味かなぁ?

 はい、setFontメソッドの呼び出しは行われませんが、UndoManagerにメッセージは
送られています。なので、関数呼び出し!=メッセージ ということになるのではないかと
思います。


[359] Re:マルチプルインスタンス
返信


投稿者: dentom
2003/09/19 13:37

Mail:   Link:
 本多さん申し訳ない。あれは説明不足なところがあるので補足説明します。

ちなみに、NSUndoManagerの仕様は
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSUndoManager.html

例で出したコードは
Registering Undo Operations
http://developer.apple.com/documentation/Cocoa/Conceptual/UndoArchitecture/Tasks/RegisteringUndo.html
のInvocation-Based Undoにあるコードを若干変形したものです。

ここでやっていることは、drawObjectに対して色とフォント情報を変更する操作の
アンドゥー操作をしています。ここにある例題ではわかりにくいですが、
(というかApple社の資料はわかりにくいのが多いんだよなー(笑))

drawObjectには、
・setFont:フォント情報 color:色情報 ← フォントと色を変更する
・font ← この時点で設定されているフォント情報をえる
・color ← この時点で設定されている色情報をえる
というメソッドがあります。たとえば

[drawObject setFont:newFont color:newColor];

とすることは「drawObjectのフォントをnewFontにし、色をnewColorにする」
という意味です。もしも、この操作を取り消したいならメソッドを呼び出す前の
フォント情報と色情報を引数にして、setFont:フォント情報 color:色情報を呼べば
いいわけです。つまり、

id aOldColor = [drawObject color];
id aOldFont = [drawObject font];
[drawObject setFont:aOldFont color:aOldColor];

がアンドゥー操作になるわけです。しかしアンドゥー操作の登録時点で
こんなことをするわけにはいかない。未来の時点でユーザーがアンドゥーメニューを
呼ばれた時点で以上の3行を呼ぶようにしないと意味がない。
メッセージ=メソッドを意味するプログラミング言語の場合はおそらく上の3行を
まるまる関数にして、関数ポインタをアンドゥースタックに登録するところですが
ここであの例題のような

id aFutureObject = [myUndoManager prepareWithInvocationTarget:drawObject];
id aOldColor = [drawObject color];
id aOldFont = [drawObject font];
[aFutureObject setFont:aOldFont color:aOldColor];

という奇怪なコードでも似たようなことができるわけです。
このときaFutureObjectというのが奇妙なオブジェクトで、こいつに対して
アンドゥー操作のメッセージを送っているのですが、実はこんなことをしても
「setFont:フォント情報 color:色情報」をaFutureObjectは実行することはない。
実行されるのは未来の時点でユーザーがアンドゥーメニューを選んだときのみ。
要するに現在のメソッド実行ではなく、未来のメソッド実行を指示してます。
これが“先物予約”と言ったゆえんです。
aFutureObjectは“未来の時点でのdrawObject”を表現しているわけです。

前橋さん流の関数呼び出しの定義では、あくまで同期的、つまり
メッセージの発行がただちに関数の呼び出しと戻りを実行させるはずだから、
こういう“先物予約”は前橋さん流の関数呼び出しとは違うと
私は解釈したので例示したのですが。


[358] Re:マルチプルインスタンス
返信


投稿者: 本多
2003/09/19 13:05

Mail:manybook@msc.biglobe.ne.jp   Link:
 > >  objective-Cとかで できる(?)って言ってる「動的束縛」ってどんな機能でしょう?
> > 実行時に関数(の様なもの)を(関数名以外の何かの手段で)選択する機能かな?
> method_call(shape, "draw");
> と書かれたら対応テーブルを検索してdraw()メソッドを呼ぶ、というような
> 機能です。
なるほど。C言語的な用語で解釈するなら
オブジェクト毎に名前から関数を探して実行する機能って感じの解釈でいいのかな?

名前を実行時に指定されて実行するなんて機能は
Cでは言語levelでsupportされてないから、
(必要なら)objectごとに実装しなくちゃいけないと。

んで、これって、どういう場面で利用すると便利なんでしょう?

> dentomさんとのやりとりにあったように(私の解釈が合っているとすれば)、
> UndoManagerにオブジェクトの状態を復元するための関数呼び出しを
> 登録しておいて、後で呼んでもらう、ということができるわけです。

実はこのあたりのやり取りが実際わかってないです。
Objective-CとかCocoaを不勉強にも知らないのがいけないのでしょうけど、
dentomさんの書いたprogramが何を意味しているのか、
「関数コールの先物予約」が何を意味するのか...
って(ぱ)さんに言ってもしょうがないですが。

aObjがmyUndoManager(型?インスタンス?)で作成されたobjectには、
setFontというmethodは持ってない(らしい)が、
aObjに対するsetFontというmessage送信に対して、
どこかのobject(drawObject?)用のmethodを借りてきて(?)使うって感じなのかなぁ?
#どのobjectがどんなmethodを抱えているのか知らないから余計ついていけない

呼ばれない「本来のsetFont」っていうのがどこのobjectのmethodを指しているのか
最終的に呼び出されるmethodはどのobject用に実装されたものなのか、
aObjに対してそのmethodが正しい操作が行われることは、どうやって保障してるのか、
drawObjectの実装を知らないとして、どんなobjectに対して正しく動作するのは
どうやってわかるのか(myUndoManager class(?)のsuper classのどこかに
drawObjectが含まれているのかとか?)
#って、書くべきスレッドが違うかなぁ(^^;)
#dentomさんがこのスレッドも読んでくれてて、
#バカな私に優しく易しく教えてくださると助かるんですが。

>>>ついでに言うとアンドゥーが1回も発生しなかったら関数コールすら起きない。
ついでに ここらへんも。Cだろうが何だろうが
1回も発生してないevent(undo)に対して関数呼び出しは発生しないと思うんですけど、
文脈的にそういう意味で言ったんじゃないんでしょう。
methodへのlinkが呼び出されるまで形成されないっていう意味かなぁ?

> Cでこれをやろうとすると、関数ポインタを使うところまではいいんですが、
> 引数を動的に積むことができないので困りますねえ。
動的に引数をつむ場合も引数の名前を与えてあげるんでしょうか?

動的に引数が詰まれちゃったときに、
個数が期待と異なる場合や、
積む順番や内容が異なる期待するものと異なる場合や
詰まれた引数の型が異なる場合は実行時のエラーになるんですか?

# なんか使い方が難しそうf(^^;) ← 私が阿呆なだけ。
# そういう言語を利用できる環境もないんですけどね←不勉強の言い訳 f(^^;)


[357] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: dentom
2003/09/19 11:55

Mail:   Link:
 >すぐ下にありますが、いわゆる関数呼び出しの機能といったら、 
>一般に言っても、
>
>a)別の「手続きの塊」へとジャンプする。
>b)引数が渡せる。
>c)処理が終わったら戻ってくる。
>d)戻り値を返すことがある。
>
>でいいんじゃないでしょうか。この手前に動的束縛が入る言語もありますが。

これが“前橋さん流関数呼び出し”の定義だとするなら、やはり
Objective-Cのメッセージは関数呼び出しにはなりえません。
分散オブジェクトを扱う場合には“非同期メッセージ”という考えがあって
この場合、処理依頼(メッセージ)と処理そのもの(メソッド)は完全に分離します。

しかしよくわからないのは前橋さん流関数呼び出しの定義では
遅延評価(その場では処理が完結せず、後から処理される。しかし未処理で終了することもある)
クロージャ(処理される対象と処理そのものを凍結化したもの)
あたりはどうなるんでしょうかね。時間軸で同期しないなら関数呼び出しではない
と考えているとしたら、おいらの出したUndoManagerの例も関数呼び出しだと
決めつけている理由がさっぱりわからないんですけど。


[356] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: dentom
2003/09/19 11:08

Mail:   Link:
 >「クラスは構造体に毛が生えたようなものだ」ということなら、
>別に間違いでもないのでは

このへんで“見解の相違”というのがよく出ていますね。
前橋さん流のクラスの定義って何なんでしょうか?
C++では文法的な拡張としてクラスを“実装”してますけど
別に構造体に毛を生えさせたアプローチばかりがクラスの“実装”
にはならないでしょうに。なんか、この前からみなさんが
直接的/間接的に指摘している自分の知っている範囲で無理やり
説明をつけようとしている徴候がここにもありますね。

次の
>Javaで言えば、メソッド名と引数のObject[]を事前に
>UndoManagerに登録しておいて、あとでリフレクションでUndoManagerに
>呼び出してもらう、というのに相当することをしてますか?
もそうです。無理に自分が知っている範囲で答えを導こうとしている感じ。
“Objective-Cのメソッド解決はJavaのリフレクションのようなもの”
と思ってらっしゃるのなら“違う”とだけ答えておきましょう。

>>呼び出す相手が決まっているのであれば、機能的に関数呼び出しと変わらない。
>これの否定にはなっていないのでは。

呼び出す相手もあとから動的に変更できますけど、ただ実用的な意味はどれだけ
あるのかは疑問ですが。いずれにせよ、ここまで議論を重ねてきてわかったこと
は前橋さん言うところの関数呼び出しというのは“前橋さん流の関数呼び出し”
ということで自己完結しているような気がします。それが良いとか悪いとかは
言いませんが、これはオレ様流の定義であって、世間一般での定義とは微妙に
ズレているということをどこかで明記しないと、いくらでもつっこむ人は
今後もどんどん出てくるでしょう。


[355] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: sumim
2003/09/19 11:06

Mail:sumi@mac.com   Link:
 > なお、Schemeのような言語まで含めて考えると、非同期メッセージで
> あっても、関数の一種だと言うことだってできると思います。
> もちろん現在の文脈では、そういう話をしているわけではなく、
> オブジェクト指向言語のメッセージという言葉は、もともとは
> Actor モデルのメッセージから来ているのにも関わらず、Smalltalk
> を含めほとんどのオブジェクト指向言語では、Actor的な非同期
> メッセージの意味は失われていて、同期メッセージの意味しか
> 残っていない、そして同期メッセージは、(SchemeやABCLや
> Concurrent Smalltalkではない)通常の言語の、関数/手続き
> 呼びだしと、実行モデル的に等価である… という話をしています。

了解です。分かりやすい説明、ありがとうございました。
なるほど、Actor モデルに照らし合わせれば、Smalltalk で
“メッセージ”をメッセージと呼ぶのは勇み足だという主張ですね。

ただ、非同期メッセージを扱えるプログラミング言語において、
Actor モデルに立脚しているユーザーが、同期メッセージをして
その実行モデルが“関数”と等価だからといってそう呼称することを
推奨してそれが通るか…という点については議論の余地はあると思います。

たとえば、Smalltalk は内部的に goto 文すら使いますから…実行モデル
まで還元して話をしようとすると、私のようなエンドユーザーの視点からは
かなりずれた議論に落ち込んでしまうような危惧はなくもありません。
でも、「単なる関数呼び出し」派の主張は当初より、尊重できるように
なりました。感謝します。

今回の件は、「Actor モデルを想定しないなら、オブジェクト指向するのに
“メッセージ”などというメタファはそもそも無用である」という
落としどころを(少なくとも自分の中では(^_^;))見いだしておきたいと
思います。ときに、kit さんは Lisper and/or Schemer ですか?


[354] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: kit
2003/09/19 04:37

Mail:   Link:
 かりやん さん wrote:
> AppleScriptは、OSA (Open Scripting Architecture) というプロ
> セス間通信を目的としたアーキテクチャ上に構築された言語です。
> OSAに準拠した言語では、外部オブジェクトに対する全ての操作が
> メッセージ(AppleEvent)を介しています。AppleEventは「宛先」「
> 命令」「データ」からなるOS標準のメッセージ塊で、これは言語仕
> 様に影響されません。

おお、なるほど。
それなら確かに AppleScript の場合も関数呼びだしと呼ぶのは
不適当かもしれません。

> …実際にメッセージを介した通信さえ「関数呼び出しだ」と仰るな
> ら、これ以上説明のしようがないんですけど (^ ^;

AppleScript の OSA 呼びだしって、future や continuation に相当
するような非同期メッセージ機構もサポートしているんでしょうか?
もししているなら、間違いなくメッセージという呼び方をすべきですね。
そうではなく、単なる遠隔手続き呼びだしであり、処理の依頼と
結果を待つ間に別の処理をはさむための一般的な構文がないようで
あれば、一種の関数と呼んでもいいかも。

> > オブジェクトが並列動作するような処理系では、c)を満たさないから
> > 関数呼び出しとは言えないだろう、と私は思っています。

> 非同期の「関数呼び出し」は別に珍しくありませんが…

遠隔手続き呼びだし機構としては珍しくないですが、言語の関数/メソッド
呼びだし機構自体に非同期処理が組み込まれていることは、むしろ稀だと
思います。もちろん、ABCL や Scheme など、そういう機構が存在する
言語もありますが。

たとえば Java の Synchronized の機構は、モニタの一種であり、関数
呼びだしとしては同期呼びだしです。Java の場合、実行スレッドは
メソッドを呼ばれる側のオブジェクトではなく、呼び出す側のオブジェクトに
付随する属性ですし。

これに対し、Actor モデルの場合、呼ぶ側と呼ばれる側のオブジェクトで
別々に実行スレッドが存在します。

 ここで注意して欲しいのは、言語仕様としては同期呼びだし (関数
と等価なもの) しかサポートしていなくても、処理の依頼と結果を
待つ間に別の処理をはさむこともできるという点です。これには主に
2種類のやり方があります。
 1つは、依頼と結果待ちに別々の関数呼びだし (同期メッセージ)
を用いる方法です。ここで、依頼される側のオブジェクトは、
依頼された時に (依頼する側の実行スレッドを使って) 処理用の
別スレッドを起こします。結果待ちのメソッドは、その中で、この
処理用スレッドの完了を待てば良いわけです。もちろん、こういう
やり方の場合、オブジェクトの実装の方で、依頼と結果待ちの2つの
メソッドをサポートしている必要があります。
 もう1つの方法は、依頼する側で別のスレッドを起こし、その新しい
スレッドを使って依頼を行なうやり方です。
 結局、できることは、同期であっても非同期であってもあまり変わら
ないと言えるかもしれません。違いは、実行モデルとして、呼ばれる
側に常に実行スレッドが存在するモデルか (これが非同期)、それとも
呼ばれる側は呼ぶ側の実行スレッドを借りるモデルか (これが同期) と
いうことに尽きるかもしれません。

これで、sumim さんの
> 非同期だと単なる関数呼び出しではなくなるのはなぜなんでしょうか?
という質問に対する答にもなっていることを期待しているんですが、
OKでしょうか?

なお、Schemeのような言語まで含めて考えると、非同期メッセージで
あっても、関数の一種だと言うことだってできると思います。
もちろん現在の文脈では、そういう話をしているわけではなく、
オブジェクト指向言語のメッセージという言葉は、もともとは
Actor モデルのメッセージから来ているのにも関わらず、Smalltalk
を含めほとんどのオブジェクト指向言語では、Actor的な非同期
メッセージの意味は失われていて、同期メッセージの意味しか
残っていない、そして同期メッセージは、(SchemeやABCLや
Concurrent Smalltalkではない)通常の言語の、関数/手続き
呼びだしと、実行モデル的に等価である… という話をしています。



[353] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: かりやん
2003/09/19 03:37

Mail:   Link:
 (ぱ)さん wrote:
> この部分を書いたのはkitさんですが…

あ、これは失礼しました。

(ば)さん wrote:
> 今まで散々出てきた「動的束縛」の話なんじゃないでしょうか。
> 相手が別の言語にブリッジされているというだけで。

違いますね。

AppleScriptは、OSA (Open Scripting Architecture) というプロ
セス間通信を目的としたアーキテクチャ上に構築された言語です。
OSAに準拠した言語では、外部オブジェクトに対する全ての操作が
メッセージ(AppleEvent)を介しています。AppleEventは「宛先」「
命令」「データ」からなるOS標準のメッセージ塊で、これは言語仕
様に影響されません。

…実際にメッセージを介した通信さえ「関数呼び出しだ」と仰るな
ら、これ以上説明のしようがないんですけど (^ ^;

(ぱ)さん wrote:
> オブジェクトが並列動作するような処理系では、c)を満たさないから
> 関数呼び出しとは言えないだろう、と私は思っています。

非同期の「関数呼び出し」は別に珍しくありませんが…
これは、正直言ってちょっと意味が分かりません。

関数呼び出しじゃなければ、いったい何なんでしょうか。


[352] Re:q
返信


投稿者: (ぱ)
2003/09/19 03:37

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > 「なぜわからなくなってしまうのか?」のページの
> 「プログラムコード上ではミサイルクラス… (略)」
> あたりの<q>タグが対応していないようです。

ご指摘ありがとうございます。修正しました。


[351] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: (ぱ)
2003/09/19 02:17

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > (ぱ)さん wrote:

この部分を書いたのはkitさんですが…

> set命令を例にとると、set命令を表わす関数はAppleScript上のど
> こにも存在しません。

というのは、今まで散々出てきた「動的束縛」の話なんじゃないでしょうか。
相手が別の言語にブリッジされているというだけで。

> (ぱ)さん wrote:
> > 機能的に関数と同じだから関数だ
...
> 「関数の機能」を明示して頂かないと、誰も反論できないと思うん
> ですが。

すぐ下にありますが、いわゆる関数呼び出しの機能といったら、
一般に言っても、

a)別の「手続きの塊」へとジャンプする。
b)引数が渡せる。
c)処理が終わったら戻ってくる。
d)戻り値を返すことがある。

でいいんじゃないでしょうか。この手前に動的束縛が入る言語もありますが。

で、オブジェクトが並列動作するような処理系では、c)を満たさないから
関数呼び出しとは言えないだろう、と私は思っています。


[350] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: かりやん
2003/09/19 01:55

Mail:   Link:
 (ぱ)さん wrote:
> シンタックスに騙されてるってことはありませんか?

それはありません。

set命令を例にとると、set命令を表わす関数はAppleScript上のど
こにも存在しません。この言語にも関数(subroutine)の概念はあり
ますが、少なくともこの言語に於ける「命令」は「関数」ではなく
「メッセージの型」として定義されています。表記上どう見えよう
と、これが関数でないのは定義として明らかです。

それと、プログラムの内容を字面だけ他の言語に変換しても無意味
だと思いますよ。私から見れば「同じことをしているとは到底思え
ない」で終わりで、そこに論議の余地はありませんから。

いや、もしかしたらLispでこれと同じ1文を書けば、プロセス間通
信を実現するためのメッセージ機構があっさり実現できるのかも知
れませんが…

(ぱ)さん wrote:
> 機能的に関数と同じだから関数だ

それって気分の問題では?

「関数の機能」を明示して頂かないと、誰も反論できないと思うん
ですが。


[349] Re:関数ってなんですか?等
返信


投稿者: (ぱ)
2003/09/19 01:54

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > この「関数」というのは一体どんなモノを想定しているのでしょうか。 
> 雰囲気としてはある命令群から別の命令群へのジャンプを想定しているようですが。

命令群、というと機械語のようですがそれはさておき。

・引数が渡せる。
・処理が終わったら戻ってくる。
・戻り値を返すことがある。

というのを追加しておいてください。

日記読みました。関数が副作用を持ったり、値を返さない関数を
手続きとして扱ったりすることに抵抗を持つ人はいるわけですが、
それはこの際関係ないというか


> 既存の説明方法の欠点を挙げる事は学習者に対してあまり利益が無いと
> 思います。トラウマと劣等感を軽減する程度でしょう。不毛です。

不毛とは思いません。トラウマと劣等感を軽減できるのなら。

> オブジェクト指向においてはインスタンスに処理を依頼するという
> 考え方(気持ち)で動作を分析し、その考え方でコードを作成する
> ことが望まれます。

いきなりこんな抽象的でアイマイモコとした説明をされても、
少なくとも私は納得できないわけで。
同じように考える人が多くいると思うからこそ、こういう文章を書いて
いるわけです。

> メソッド呼び出しの記法で混乱し挫折する程度の人は多分そのままの
> 思考様式ではオブジェクト指向を習熟するのは困難でしょう。
> これは説明方法には依らないと思います。というか、そういう人がど
> うやってC言語を習得したのか謎ですが・・・。

記法ごときで混乱する人がいるとは思いません。
記法ごときに過剰な説明を載せるから、混乱し挫折する、と言っているのです。

言語機能の記法としては、第1引数が前に出てきただけ。
まずそれを押さえれば、理念は後からついてくる。

一応書いておくと、このページとほぼ同じ主張をしている
「Java謎+落とし穴徹底解明」には、メソッドなんて第1引数が前に出て
きただけだ、とも書きましたけど、その後に、
『「オブジェクトに仕事をさせる」という発想』
という章もあるんですよ。

というわけで先を書きたいんですが、書いてる時間がない状態です(;_;)


[348] Re:メッセージ送信の比較
返信


投稿者: (ぱ)
2003/09/19 01:23

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > こんちは。HAPPY Macintosh Developing TIME! っていう
> ホームページをやっている mkino っていいます。

どうもです。

ところでいきなりオセロ盤の話に戻りますけれど、私が書いたオセロの実装

http://member.nifty.ne.jp/maebashi/javaworld/index.html

では、複数のBoardインスタンスを作っています。今日思い出したんですが。
コンピュータの思考ルーチンで、先読みのためどんどん盤を生成するからです。

だから、staticに根元を押さえたBoardを1個作ってもいいけど、
グローバル変数じゃ困りますね。

> C++ と Java と Objective-C の、メッセージ送信と
> メソッドの実現方法について比較してみました。
> http://homepage.mac.com/mkino2/oop/messaging.html

勉強になります。特にObjective-Cについては。

「ポインタという概念がないので不可」はさすがに気になりますが… (^^;
「関数ポインタ」ならそうだと思うんですが。

> メッセージ送信を関数呼び出しと呼んで、
> これだけのことに気をつけることができますかね。

いや、だから、動的束縛については、最初に知らなければならないことでは
ないだろう、ということです。JavaだってObjective-Cとは異なるとはいえ
動的なメソッド選択はありますが、私はそれを承知で「関数呼び出しだ」と
言っているわけですから。


[347] カプセル化
返信


投稿者: たかお
2003/09/19 01:15

Mail:   Link:
 「カプセル化という幻想」が何を言いたいのかわかりません。
「単なる構造体的な「データを保持するためのクラス」と位置づけるのであれば、 xとyを最初からpublicにした方がまだマシというものでしょう」と説明してますが、そもそも単なるデータを保持するためのクラスであり、かつそのデータ構造を隠蔽する必要が無い(つまりカプセル化の必要が無い)例をあげておいて「カプセル化という幻想」とは、いったい何を説明したいのでしょうか?
これではまるで「setX(), getX()のように単にデータにアクセスするだけのprivate関数を用意するのなら、変数xをprivateにしたほうがマシ」という説明に読めます。確かにこの後に追加・変更のない「この例」ではそれが当てはまるでしょうけど、これだけ面倒なコーディングをしてきちんとカプセル化したメリットの説明が無いのなら、幻想も何も無いと思うのですがいかがでしょうか。
つまりカプセル化について何を言いたいのでしょう?


[346] Re:マルチプルインスタンス
返信


投稿者: (ぱ)
2003/09/19 00:56

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > > シングルインヘリタンスながら、継承とメソッドオーバーライドまで
> > 実現しています。
> 用語に対する私の理解が少し混乱してます。
> インヘリタンスって継承と同じ意味じゃないんでしたっけ?

同じ意味でよいと思います。「単一継承ながら継承を実現し、かつ、
メソッドオーバーライドまで実現している」という意味で書いています。

> となると多重継承がうまくできるのがオブジェクト指向言語の特徴なのかしら?

いや、Cでも継承は無理にやればできるけど、ソースがキャストの塊に
なったりして美しくない、ということでしょう。
そういうことをやりたければオブジェクト指向言語を使え、と。

> #多重継承ってあまりよくないことだと聞いたことがあったような。
> #理由は忘れたけど。っていうか私の勘違いかも。f(^^;)

反復継承とかになるとわけわからん、というのが理由だと思います。

> ついでに質問です。
> objective-Cとかで できる(?)って言ってる「動的束縛」ってどんな機能でしょう?
> 実行時に関数(の様なもの)を(関数名以外の何かの手段で)選択する機能かな?

Cで説明するなら、「無理矢理インヘリタンス」
http://member.nifty.ne.jp/maebashi/programmer/c_yota/inherit.html
のような実装を考えたとして、クラスディスクリプタに対し
関数ポインタと名前の対応テーブルを付けてやり、

method_call(shape, "draw");

と書かれたら対応テーブルを検索してdraw()メソッドを呼ぶ、というような
機能です。

これだと、インスタンスによって別々のdraw()メソッドを呼ぶことができます。

そこまではJavaやC++でもメソッドオーバーライドを使えばできるわけですが、
この方法なら、名前さえわかれば「全く知らない関数」を呼び出すことが
できます。

dentomさんとのやりとりにあったように(私の解釈が合っているとすれば)、
UndoManagerにオブジェクトの状態を復元するための関数呼び出しを
登録しておいて、後で呼んでもらう、ということができるわけです。

Cでこれをやろうとすると、関数ポインタを使うところまではいいんですが、
引数を動的に積むことができないので困りますねえ。

> XtNameToWidget()+ 関数() とか、dlopen() + dlsym()みたいな動作をするんですか?

少なくともXtNameToWidget()はインスタンス検索だからまったく別物では。


[345] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: (ぱ)
2003/09/19 00:49

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > 特にC++なんて演習させたら「クラスは構造体のことだ」
> と言い出す人がたまにいますけど指導者が悪いのかも。

「クラスは構造体と全く同じものだ」と言い出す人はまさかいないと
思うわけで、「クラスは構造体に毛が生えたようなものだ」という
ことなら、別に間違いでもないのでは。問題は、どんな毛が生えて
いるかをちゃんと理解することです(ずいぶん毛深いですが)。

> だとしても違いますね。mkinoさんの掲示板で出した例で説明すると
> Objective-CというかMac OS XのCocoa限定ですけどNSUndoManagerと
> いうクラスでアンドゥー操作を登録するとき

これって、Javaで言えば、メソッド名と引数のObject[]を事前に
UndoManagerに登録しておいて、あとでリフレクションでUndoManagerに
呼び出してもらう、というのに相当することをしてますか?

わざわざaObjにメッセージを送っているのは、そうしないと
NSInvocationとやらが手に入らないから? (違うような気がする)

私の解釈が合っているとするなら、
このように、UndoManagerから、UndoManagerとは縁もゆかりも
ないオブジェクトのメソッドを呼び出してもらうことができる、
というのはObjective-C流の動的束縛のメリットだと思います。
でも、
>呼び出す相手が決まっているのであれば、機能的に関数呼び出しと変わらない。
これの否定にはなっていないのでは。

継承によらない動的束縛には、それはそれでメリットがあると思うんですよ。
そのために、Javaだってリフレクションがあるわけですし。
でも、それは最初に教えるべきことでもないでしょう。


[344] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: sumim
2003/09/18 23:41

Mail:sumi@mac.com   Link:
 コメント、痛み入ります。大変ですね(^_^;)。

> Smalltalkの方が引数の意味が分かりやすく、コメントに頼らずに済むのは
> 確かでしょうが、それは「"オブジェクト指向"パラダイム」のおかげでは
> ないのでは。

となると、何のおかげなのでしょう?

それが何にしても、わざわざこうした変わった記述方法を採用し、ある種の
メリットを生じ得たのは、従来の単なる関数呼び出しの文に「オブジェクトに
対するメッセージの送信」という意味を持たせたことと無関係ではないと思います。

まあそこまでけんか腰にならなくとも、“単なる関数”を「メソッド」と呼び、
動的結合のための機構を挿み、引数配置の変更した“ちょっと変わった関数呼び出し”を
「メッセージ」と呼ぶことでユーザーが幸せになれる言語もあるのだから、C++ や
Java で路頭に迷う人が多いからといって、関数呼び出しのメッセージへの置き換えを
頭ごなしに否定してしまうのはいかがなものかと、そういうお話しです。

> > 他方でクラス指向手法は、やっかいなことに、“オブジェクト指向”言語
> > でも(クラスのない Self であってすら)適用可能で、むしろ必須とされます。
>
> Selfまで出てくると話が全く違ってくるわけで… やっぱり、
> 「言語としてJavaを使う」というのをもうちょっと明確にした方がよいですね。

なぜ Self なら…という疑問が残りますが(笑)。それはさておき、想定する言語を明確に
していただきさえすれば、というところに尽きます。ひとこと入れていただくだけ
でずいぶんと印象が違ったものになると思います。よしなに。


[343] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: dentom
2003/09/18 23:00

Mail:   Link:
 >演習させたら「結局関数呼び出しじゃないか」と言い出すに一票。 

それは演習させる内容によりけりでしょう。
C++やJavaばっかりやってたら知りませんけど。
特にC++なんて演習させたら「クラスは構造体のことだ」
と言い出す人がたまにいますけど指導者が悪いのかも。

>この「メッセージ送出=関数呼び出し」
>に関しては、別に実装の話をしているつもりはないんです。
>「機能が同じだから」同じだといっているのです。

だとしても違いますね。mkinoさんの掲示板で出した例で説明すると
Objective-CというかMac OS XのCocoa限定ですけどNSUndoManagerと
いうクラスでアンドゥー操作を登録するとき
prepareWithInvocationTarget:メソッドを使いますが
id aObj = [myUndoManager prepareWithInvocationTarget:drawObject];
[aObj setFont:[drawObject font] color:[drawObject color]];
という感じでメッセージを送ってしまうことになります。
このときaObjそのものはsetFont:メソッドなんか持っていません。
(aObjの正体はNSUndoManagerインスタンス)
結局どうなるかと言うとメソッドがないものだからforwardInvocation:メソッドが
呼びだされることになって、そこからアンドゥー操作をオブジェクト化する
という作業が待ち受けているわけです。本来のsetFont:メソッドを呼ぶのでなく。
こうなってくると、もはや“単なる関数コール”とはとても呼べない代物です。
無理にたとえるなら“関数コールの先物予約(笑)”とでも呼ぶべきものですかね?
ついでに言うとアンドゥーが1回も発生しなかったら関数コールすら起きない。

あとはLISPのようなものでOOPする場合に機能的に関数呼び出しと
呼べない例があったように思いますが、それはLISPerな人にまかせましょう。


[342] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: sumim
2003/09/18 22:48

Mail:sumi@mac.com   Link:http://squab.no-ip.com:8080/about
 > 上記の Smalltalk におけるメッセージと、ABCL における非同期な
> メッセージの両方を含みますから、「メッセージとは関数呼びだしだ」
> と単純に言い切るのはまずいと思います。
> これに対し、「Smalltalk におけるメッセージとは一種の関数呼びだしだ」
> と言うことには特に問題を感じません。
> これが Smalltalk ではなく、Concurrent Smalltalk だったら、「関数
> 呼びだしとは違う」ということになるんでしょうけど。

非同期だと単なる関数呼び出しではなくなるのはなぜなんでしょうか?
お手数をおかけして恐縮ですがちょっとかみ砕いて教えていただければさいわいです。


[341] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: (ぱ)
2003/09/18 22:30

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > 従来の構造化パラダイムでは手続きに対してパラメータが送られ、手続きは
> あらかじめ決められたパラーメータの組み合わせに対応して処理を行ないます。

昔、矩形領域を指定する関数で、てっきり

set_view_area(view, xmin, ymin, xmax, ymax);

だと思って呼んでみたら、実は

set_view_area(view, xmin, xmax, ymin, ymax);

だったのではまったことがあります。

もしCが、プロトタイプ宣言に引数名を書くことを強制し、かつプロトタイプ宣言に

set_view_area(View *view, double xmin, double xmax, double ymin, double ymax);

とあったら、

set_view_area(view:view, xmin:0, xmax:0, ymin:100, ymax:100);

のように呼ばないとコンパイルエラーだ、という仕様になっていたとしたら、
こういうポカは防げますよね。これがC++では

view->set_area(xmin:0, xmax:0, ymin:100, ymax:100);

になるんでしょう。

> “オブジェクト指向”パラダイムでは、メッセージがオブジェクトに対して
> 送られ、オブジェクトはメッセージに対応するあらかじめ決められた処理を
> 行ないます。構造化パラダイムでは、手続き呼び出しで
>
> replace(aString, oldString, newString)
>
> と書きますが、“オブジェクト指向”パラダイムでは
>
> aString replaceAll: oldSubstring with: newSubstring
>
> のようにオブジェクトに対するメッセージ送信式で記述します。両者を比較する
> と手続き呼び出しではユーザーに対して、各パラメータが意味するところを
> 伝える手段にメッセージ式より制限されており、コメントなどの別の手段に
> その役割りを求めなければいけないことが分かります。

Smalltalkの方が引数の意味が分かりやすく、コメントに頼らずに済むのは
確かでしょうが、それは「"オブジェクト指向"パラダイム」のおかげでは
ないのでは。

私が何か誤解しているようでしたらご指摘ください。

> 他方でクラス指向手法は、やっかいなことに、“オブジェクト指向”言語
> でも(クラスのない Self であってすら)適用可能で、むしろ必須とされます。

Selfまで出てくると話が全く違ってくるわけで… やっぱり、
「言語としてJavaを使う」というのをもうちょっと明確にした方がよいですね。


[340] Re:"Cプログラマのための"
返信


投稿者: (ぱ)
2003/09/18 22:11

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > だったら突っ込みはもっと少なかったのではないかなぁ(´Д`)

「Cプログラマのための」という限定条件を付けるべきだった、ということは、
現在は限定がないせいで、対象でない人も対象になっているように見える、
ということですね。それは誰でしょうか。

Pascalなら関数とプロシジャは分かれてるぞ、とか、
BASICのGOSUBしか知らない人は、関数呼び出しなんて言っても分からんぞ、とか、
古いCOBOLやFORTRANしか知らない人は構造体やポインタやmalloc()なんて
言っても分からんぞ、ということなら、確かにそうですね。

> 「関数呼び出し」などという大仰な名前にこだわっているのは
> そこらへんに根っこがありそうですけど。

別に「サブルーチンコール」でも「プロシジャ」でもよいわけなんですが。
似たような機能は、BASICとかはともかくたいていの言語にありますよね。

その機能を知っている人に対し、(動的束縛が入るとはいえ)ほぼ同じ
機能について説明するのに、別の言葉を持ち出す必要はないだろう、
ということです。

今書いているのは「Smalltalkerのためのオブジェクト指向再入門」で
ないことだけは確かです。そんなの矛盾してるし。

> setter/getter意味ねーのか全部publicでいいや、と思わせがち
> なとことか、言葉足らずの部分もわかっててやってるにしちゃ
> 罪深すぎます。

オセロの例を見れば分かると思うんですが、カプセル化自体、
否定しているつもりはありません。
あらためて見てみると、「カプセル化という幻想」というタイトルは
さすがにまずいですね。ちょっと考えます。


[339] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: (ぱ)
2003/09/18 21:58

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > >「人間、誰しも低レベルの概念のほうが理解が早いものです」。 
>
> そして、これの最大の落とし穴は
> 低レベルの説明で理解したつもりになって、それ以上に思考を進めようとしない
> 弊害に陥りやすい点です。

それはそこで止まってしまうのが悪いわけですが、いずれにしても、
一歩も踏み出せないよりはマシ、理念は後から付いてくる、と
私は思っているわけです。

> >「理念」の説明を延々とされることが、結局理解の妨げになっていると
> >思いませんか?
>
> これに関しては別の掲示板で書いたけど、説明をえんえんと聞かすよりも
> とっとと演習させたほうが早いだろうと思います。人間の理解というのは
> どうしても自分が経験した範囲や教育の範囲に縛られるので、その範囲を
> はずれたことはわかったつもりになっていて、そうでもない、と…。

演習させたら「結局関数呼び出しじゃないか」と言い出すに一票。

> 前橋さんの“メッセージ送出=単なる関数呼び出し”説が危険なのは
> 前橋さんが知っている実装の帰納的な類推で言っているだけであって
> 今後出てくるであろう/あるいは前橋さんが知らない実装で反証される
> 可能性がいくらでも出てくるであろうという点です。

前の反論のふたつ目で書いたんですが、この「メッセージ送出=関数呼び出し」
に関しては、別に実装の話をしているつもりはないんです。
「機能が同じだから」同じだといっているのです。

メソッド呼び出しの「実装」が動的束縛になっているからといって、
呼び出す相手が決まっているのであれば、機能的に関数呼び出しと変わらない。
むしろこの場合「動的束縛である」ということの方が実装詳細です。

もちろん相手が決まらない場合は機能も違うわけですが、それについては
「別に最初に知らなければならないことではない」と思っているわけです。


[338] オブジェクト指向のこんな説明
返信


投稿者: 2
2003/09/18 21:54

Mail:   Link:
 初めまして。

「オブジェクト指向」ってけっこう曖昧だし、
けっこう複雑なシステムになってやっとメリットが
出てくるのではないかと、と思うので、説明しづらい
のではないかと思うのですが。

などと言いつつ自分なりの説明に挑戦してみようと思います。
勝手にやってしまって少し申し訳ないのですが。
たぶん、内容はそこまでかぶってないと思いますので。

例として、数字を表す文字をintに変換する関数cToInt()と、
文字列を数字にする関数sToInt()を考えます。

 struct Character;
 int cToInt(struct Character *c);
 int sToInt(struct Character *s[]){
   int sum = 0;
   for( ; !cIsNull(*s); ++s){
     sum = sum * 10 + cToInt(*s);
   }
   return sum;
 }

ここで重要なのは、typedefの部分です。
なんかstruct Characterの定義が無いのですが、
「とりあえずCharacterという構造体がある」という意味です。
実際ここまではただのCでも文法違反ではないと思います。
ここからがオブジェクト指向な所(Cでは文法違反になる所)です。

 struct ASCIICharacter(Character){
   unsigned char data;
 };

 int cToInt(struct ASCIICharacter *c){
   return c->data - '0';
 }

ASCIICharacterのtypedefの後に(Character)が付いています。
これは、ASCIICharacterがCharacterとして使われても
良きに計らってくれる、ということを意味しています。
例えば、ASCIICharacter*の配列をsToIntの引数として
呼んだ時はちゃんとASCIICharacter*としてあつかってくれます。

しかし、これだと、単なる手間です。。あれ?

その後、sToInt()はいろんな所で使われるようになりました。
そして、16ビットのユニコードの対応をしないといけなくなりました。
そこで、こんな風に書きます。

 struct UnicodeCharacter(Character){
   unsigned short data; /* shortを2ビットと勝手に決めつけてますが */
 };

 int cToInt(struct UnicodeCharacter *c){
   if(c->data >= (unsigned short)'0' && c->data <= (unsigned short)'9'){
     return c->data - '0';
   } else if(c->data >= KANJI_ZERO && c-<data <= KANJI_NINE){
     return c->data - KANJI_ZERO;
   }
 }

こうすると、UnicodeCharacter*の配列を引数としてsToInt()を呼んでも
内部で上の(ASCIICharacterのところで定義した物ではない)cToInt()が呼ばれます。
引数がASCIICharacter*の配列なら、内部でASCIICharacterの所で定義された
cToInt()が呼ばれます。

こんな感じだと、分かりやすいかな、と思ったのですが。
ここで書くのはまずかったかな〜。
自分がまともに理解をしているかを調べてもらうという目的も含めて
書いてみました。


[337] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: (ぱ)
2003/09/18 21:48

Mail:PXU00211@nifty.ne.jp   Link:http://member.nifty.ne.jp/maebashi/
 > というのは、並列オブジェクト指向言語の中には、ABCL のように、メッセー
> ジ送出が、異なる実行スレッドへの通信メッセージ送出である言語もあるから
> です。もし、この文章が

確かにスレッドが異なってしまうと、関数呼び出しとは明らかに違う
ものになりますよね。もともと問題の文章は
| こんな説明を読むと、まるで各オブジェクトにそれぞれプロセスが
| 割り当てられていて、プロセス間通信で動作するかのように思えますが
という文脈で書いているわけでして。

「ちゅーちゅーねずみ」さんにも指摘されていますが、ここではJavaを
使っているわけですから、それをもうちょっと前面に出したほうが
よさそうです。ひとことでオブジェクト指向言語といってもいろいろ
ありますから。

> > 世間の入門書では、オブジェクト指向といえば「カプセル化」「継承」
> > 「ポリモルフィズム」ということになっていると思いますが、
>
> このあたりの文章は、ちょっと過激だと思います。:-)

うーん、「このあたりの文章」に関して言うと、過激であるという認識は
自分ではないんですが(^^; 他のところはともかく(^^;;;

> 「カプセル化」「継承」「ポリモルフィズム」が、オブジェクト指向『言語』
> としての必要条件だというのは確かだと思うし、たぶん(ぱ)さんも、その点
> について異論はないんじゃないですか?

そうですね。ここで想定している「オブジェクト指向」言語としては
必要条件だと思います。ただ、「カプセル化はもう知ってるだろうし
継承やポリモルフィズムはもうちょっと後でよい」と言ってるつもり
なんですが、

> このあたりの文章は、これらについての否定的な表現を抑えて、これらも
> あるけど、それだけじゃないんだってことだけ強調した方が、万人に受け
> 入れられやすいと思います。

「否定的」と取られてしまうかなあ…

> あと、「マルチプルインスタンス」というのは、「マルチプルインヘリタンス」
> と字面が非常に似ているので、一言「インヘリタンスじゃなくてインスタンスだよ」
> って断っておいた方が良いような。

了解です。言われてみればそうですね。


[336] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: kit
2003/09/18 21:18

Mail:   Link:
 sumim さん wrote:
> 私は、
> Simula-67 C++ | Java Ruby NewtonScript | Objective-C Smalltalk Self
> と線引きしています
:
> オブジェクト指向”パラダイムでは
> aString replaceAll: oldSubstring with: newSubstring
> のようにオブジェクトに対するメッセージ送信式で記述します。

うーん、僕は Smalltalk についても、一種の関数呼びだしと考えて
問題ないと思ってます。
オブジェクト指向の用語でメッセージという言葉を使う理由って、
オブジェクト指向言語が actor モデルの影響を受けているからじゃ
ありませんでしたっけ? で、Scheme の実装に関する論文で、実は
actor とは (lambda 計算における) 関数にほかならないということが
実証されていたと思います。まあ、scheme の関数には continuation
があるので、普通の言語の関数よりは強力なんですが、Smalltalk や
Java などの普通のオブジェクト指向言語の場合、continuation は
ありませんから、関数そのものと言って特に問題ないと思います。

これに対し、ABCL など並列オブジェクト指向言語の一部が採用している
非同期なメッセージは (これも actor 理論の直系なわけですが)、
(continuation のない言語における) 関数とは異なります。

オブジェクト指向言語の「メッセージ」という言葉を出した場合、
上記の Smalltalk におけるメッセージと、ABCL における非同期な
メッセージの両方を含みますから、「メッセージとは関数呼びだしだ」
と単純に言い切るのはまずいと思います。
これに対し、「Smalltalk におけるメッセージとは一種の関数呼びだしだ」
と言うことには特に問題を感じません。
これが Smalltalk ではなく、Concurrent Smalltalk だったら、「関数
呼びだしとは違う」ということになるんでしょうけど。

かりやん さん wrote:
> AppleScriptというMacOS上で動作するスクリプト言語があります。
:
> 「set name of document 1 of application "TextEdit" to "no name"」
:
> このset命令はメッセージであって、関数呼び出しではありません。

えーと、これって Lisp 風に書くと
(setf (name-of (get-document (application "TextEdit") 1)) "no name")
という一種の手続き呼びだしにしか見えませんけど。
シンタックスに騙されてるってことはありませんか?


[335] q
返信


投稿者: 竹内
2003/09/18 19:17

Mail:   Link:
 はじめまして。竹内というものです。
つまらぬことですが、
「疑り深いあなたのためのオブジェクト指向再入門」の
「なぜわからなくなってしまうのか?」のページの
「プログラムコード上ではミサイルクラス… (略)」
あたりの<q>タグが対応していないようです。


[334] メッセージ送信の比較
返信


投稿者: mkino
2003/09/18 14:45

Mail:mkino@xd5.so-net.ne.jp   Link:
 こんちは。HAPPY Macintosh Developing TIME! っていう
ホームページをやっている mkino っていいます。

C++ と Java と Objective-C の、メッセージ送信と
メソッドの実現方法について比較してみました。
http://homepage.mac.com/mkino2/oop/messaging.html
よかったらがんがん突っ込んで下さい。

メッセージ送信を関数呼び出しと呼んで、
これだけのことに気をつけることができますかね。


[333] Re:"Cプログラマのための"
返信


投稿者: かりやん
2003/09/18 14:45

Mail:   Link:
 同意します。


[332] Re:"Cプログラマのための"
返信


投稿者: sumim
2003/09/18 13:59

Mail:sumi@mac.com   Link:
 > "Cプログラマのための"
> だったら突っ込みはもっと少なかったのではないかなぁ(´Д`)

書き込み(しかも長々とした)が前後しましたが、私が言いたいのも
まさにそういうことです(^_^;)。ありがとうございます。


[331] Re:メッセージ送出=単なる関数呼び出し
返信


投稿者: sumim
2003/09/18 13:15

Mail:sumi@mac.com   Link:
 > Cプログラマだって、関数やモジュールに「お願い」する感覚はあると思うし、
> Javaプログラマなら、ひとつの「お願い」に対して「かなえるためにすること」が
> たくさんあるのは普通の話だと思いますよ。
>
> このところのやりとりで、SmalltalkやObjective-Cな人が、
> C++やJavaと、SmalltalkやObjective-Cとの間に線を引きたがる根拠が私には
> わからないのです。

OOPL の線引きには主に使用する言語によって微妙な差異があるかもしれません。
私は、

Simula-67 C++ | Java Ruby NewtonScript | Objective-C Smalltalk Self

と線引きしています(少々、マイナーな言語が紛れ込んでいますがご勘弁を(^_^;))。
中央のグループは左右のいいとこどりだと思っています。もちろん、右へゆくほど
“オブジェクト指向”をコードに反映するのに適した言語と考えています。

ここでいう括弧付きの“オブジェクト指向”問題解決は「オブジェクトに対して
メッセージを送る」というステップの積み重ねで問題解決をはかることと定義できます。
オブジェクトにメッセージを送って得られる結果もまたオブジェクトです。
そうして得られたオブジェクトに対して別のメッセージを送るか、置いておいて
別のオブジェクトに対するメッセージ送信ステップに移行するかは状況しだいです。

従来の構造化パラダイムでは手続きに対してパラメータが送られ、手続きは
あらかじめ決められたパラーメータの組み合わせに対応して処理を行ないます。
“オブジェクト指向”パラダイムでは、メッセージがオブジェクトに対して
送られ、オブジェクトはメッセージに対応するあらかじめ決められた処理を
行ないます。構造化パラダイムでは、手続き呼び出しで

replace(aString, oldString, newString)

と書きますが、“オブジェクト指向”パラダイムでは

aString replaceAll: oldSubstring with: newSubstring

のようにオブジェクトに対するメッセージ送信式で記述します。両者を比較する
と手続き呼び出しではユーザーに対して、各パラメータが意味するところを
伝える手段にメッセージ式より制限されており、コメントなどの別の手段に
その役割りを求めなければいけないことが分かります。これが、オブジェクトに対して
どんなメッセージを送るかだけを考えればよく、それをそのままコード化できる
“オブジェクト指向”言語である Smalltalk を使う私がメッセージという
メタファにこだわり、それを否定する記述に反発する理由のひとつです。

もちろん世の中の「オブジェクト指向」はこれだけではありません。むしろ、
こうした考え方よりは、Simula-67 に端を発するクラスによる抽象データ型、
換言すれば、ユーザーが定義可能なデータ型、をいかにうまく活用して問題解決に
役立てるかといういわば「クラス指向」と呼ぶべき実践的手法が主流である
のは改めて言うまでもないことだと思います。こうした手法を主軸に据えた
言語では、メッセージという概念は無用で、当然、メッセージ式という
記述方法など採用していません。したがって前述の“オブジェクト指向”
のメリットは意識の外にあり、いくら説明しても従来の手続き呼び出し
を捨ててまでの魅力は見いだせないはずです(だからそれらの言語を
使うわけですから(笑))。

他方でクラス指向手法は、やっかいなことに、“オブジェクト指向”言語
でも(クラスのない Self であってすら)適用可能で、むしろ必須とされます。
同時に、メッセージメタファの“オブジェクト指向”は抽象的だったり、
使用する言語によっては、その実装や、実際の記述方法に即していないぶん、
クラス指向アプローチの理解を邪魔する余計なものである、というのはこのページを含め、
各所で指摘されているとおりでしょう。個人的な印象では、最初の列で左にいけば
いくほど、その傾向は強まるように感じます。

ただそうした状況にあっても、メッセージの存在を想定した方が理解しやすく
本領を発揮する“オブジェクト指向”の存在を信じる向きも依然としてあるわけで、
これをご配慮いただき、こちらでの「オブジェクト指向」をして必ずしも当てはまる言語
ばかりでないと付記していただければ幸い…というのが先のコメントの意図でした。


ひとつ前の過去ログ | 目次へ | ひとつ後の過去ログ