クラスメソッドの特異メソッドとしての扱いは“シンプル化”に貢献するか
特異メソッドの、Ruby にはメタクラスがあり、クラスはそのインスタンスという扱いになっているにもかかわらず、なぜか Ruby のクラスメソッド、すなわちオブジェクトとしてのクラスがメッセージを受信して起動することができるメソッド、はこの特異メソッドで実現されている。
をうけたやりとりを移動。--sumim
↑シンプルだから、じゃないかな。
- Rubyで特異メソッドを定義すると、そのオブジェクトののクラスの子クラスとして、無名クラスが自動的に作成される(そしてそこにメソッド実体が定義される)らしい。
- だから、「クラスの(メタ)クラスを引っ張ってきて、そこにdefする」という書き方をする「必要」が無い。内部的に同じことになる(んだと思う)。
- 概念的にもシンプルだと思う。(メタ)クラスの存在を考える必要すら無いわけだから。
>シンプルだから、じゃないか
Smalltalk において「インスタンスが起動するメソッドは、それが属するクラスに定義する」というルールひとつで済ませられる方がずっとシンプルだ、と思うのはお互い様でしょうかね。いったい、それのどこがシンプル?などとさらに Self から笑われるのは必至…というのもありますが、それはそれとして。--sumim
>ルールひとつで済ませられる方がずっとシンプルだ、と思うのはお互い様でしょうか
過度(matz氏の基準で)のミニマリズムは避けたい(避けたほうが一見シンプルに見える)、という意味でしょうね。
「驚き最小の法則(最近Rubyを説明するときに使われている言葉)」ということはつまり、主観(^^;に対するシンプルさを狙う、という意味になるでしょうから。
あと、コード書くときの手数の問題も重視されてますね。ワンタッチで自分のクラスのInstanceMethod定義部分(?)にアクセスできるとか、アクセスのされ方によってはクラス(無名で)すら新作してしまうとか、を自動化(マクロ化?)しちゃってるわけで。
>(メタ)クラスの存在を考える必要すら無い
メタクラスの存在を意識しなくてよいからシンプル、という話は悔しいけど納得できます。実際、この話を書くときに調べるまで Ruby にメタクラスが存在するとは知らなかったくらいですから。--sumim
>コード書くときの手数
手数よりむしろ、クラスを意識の中心に据えてそこに作業やその作業者の意識を集中させることで(つまりこの場合、メタクラスなどもちださなくとも、クラスだけで話を済ませることができる状況を作ることで)、エンドユーザーの負担を減らすという趣向なら、それが実現するシンプリシティは理解できます。私自身は、メッセージ送信メタファにもとづくオブジェクト指向の実践にあたって、クラス定義はそのメタファにより実現されるべき作業のひとつに過ぎないととらえているので、それをことさら(たとえ実質的にそうであったとしても)中心に据えて特別扱いして新しいルールを導入する考え方は安易で嫌いですが。--sumim
>内部的に同じことになる
これは残念ながら理解できません。ちなみに戯さんの脳内で、ここでのメタクラスは Smalltalk のそれを意識しておられるのでしょうか。それともここで私の思いつかない別のメタクラスを持つ言語処理系を? たとえばお得意の俺言語とか?--sumim
>>内部的に同じことになる
>これは意味不明です。
「class self用特異クラス selfの元々のクラス; def メソッド定義; (以下略)」という書き方を近道して、
「def self.メソッド定義; (以下略)」と書けるようにした、というだけなんで、
「同じこと」です。
あ。上で間違えてますね。「クラスの(メタ)クラスを引っ張ってきて、それにインスタンス(=クラス)を作らせ、そこにdefする」です。
- rubyの「class Hoge < Fuga」やSmalltalkの「Fuga subclass: #Hoge instanceVariables: '...」つまり子クラス作りも、考えてみたらただの近道ですね。
- メタクラスに特定のクラスを作らせ、それを自分の子クラスだと認知する、という処理。
>クラス定義はそのメタファにより実現されるべき作業
「により」ですか?
「クラス定義するぞ」というメッセージ(メソッド)が有ればいいじゃん、という話ですか?
だったら、まあそれはそれでOKです。あとはそれが読み書きし易いカタチになっていれば尚OK。
#てか、何の話をしたいんでしょう?
「新しいルール」というよりは、ルールは2つしか無いんですよね、Rubyでは。
「class 云々」って書く奴と、「def hoge.fuga」って書く奴と。
で、問題(^^;はどちらも概念的にシンプルだ、ということじゃないかな。
#書き方がシンプルなのは文法策定者の単なる手柄なので、ここではさておき。
インスタンスベースとクラスベースが喧嘩せず(それどころか結構判りやすいカタチで)同居してるっていう。
「def hoge.fuga」は、単なる構文糖じゃなく(parserも弄ってるが、それはともかく)、
ものの見方を一時的にインスタンスベースに切り替えてますよ、という概念レベルの話なんだろうな。
>クラス定義はそのメタファにより実現されるべき作業
その一段前の話なんだと思う。
我々はHOGEHOGEを実現するためにクラス定義をするわけですよね。
で、そのHOGEHOGEを実現するための手段は(Smalltalkだと1つだがRubyだと)2つ有って、
1つはクラス定義、もう1つは特異メソッド定義、なのだろうな。
- HOGEHOGEに当てはまる旨い言葉が思いつかない。「プログラムの機能変更」じゃ陳腐すぎるし…
- 「オブジェクトの機能変更」でもいまいち的を得ていないし。
- うーん。クラスとかオブジェクトとかTraiatsとかいう具体的な(笑)言葉を使うと、どうも旨くハマならない…
>クラスの(メタ)クラスを引っ張ってきて、それにインスタンス(=クラス)を作らせ、そこにdefする
それなら分からないでもありません。つまり、Ruby のクラスは(かならずしも)シングルトンではないのですね。勉強になります。
- ただ、それでも「同じ」とは思えないなぁ…。エンドユーザーからの見た目は確かに同じです。
- ちなみに「クラスのクラス」と「クラスのメタクラス」では意味が違いますので、この括弧の使い方はおやめになった方がよいと思います。「クラスのクラス(=メタクラス)を引っ張ってきて、それにインスタンス(=クラス)を作らせ、そこにdefする」のほうが適切かと。分かっていてやっているんでしょうけど、老婆心ながら。
--sumim
>「クラス定義するぞ」というメッセージ(メソッド)が有ればいいじゃん、という話ですか?
ああ、これは言葉が足りませんでした。ここで「クラス定義」とは、クラスの新設に限らず、メソッド定義も含めてのトータルな意味でのクラスの定義です。まあでも「クラスを定義するぞ」に加えて「インスタンスが起動できるメソッドを追加するぞ」「インスタンス変数を追加するぞ」などなどがしかるべきオブジェクト(この場合、オブジェクトとしてのクラスなり、メタクラスなり)に対するメッセージ送信という考え方にそってできていればオッケーなので大筋ではご理解のとおりかと。--sumim
>我々はHOGEHOGEを実現するためにクラス定義をするわけですよね。
>#HOGEHOGEに当てはまる旨い言葉が思いつかない。
メッセージ送信メタファ信奉者の私としては、ここは迷わず「我々が望むメッセージを受け、期待される挙動を示すオブジェクトを実現するために…」としたいところです。そしてそのメソッド定義作業時の主役(メッセージのレシーバ)は、インスタンスナはなくオブジェクトとしてのクラスが担うのが自然だろうという話をしているつもりです。もっともメタクラスと同時に無条件に生み出されるクラスと違い、通常のインスタンスはメッセージを送ろうにもクラス定義作業時には存在しない場合が普通なので、適切だと思って送ろうにも送りようがないからクラスに…という話もなきにしもあらずですが。で、Self はコペルニクス的展開でそれをやってのけたし、Ruby は特異メソッドで、せめてクラスメソッドだけはそのシンプルさにすがろうとした、という話は成り立つと思います。--sumim
>Smalltalkの「Fuga subclass: #Hoge instanceVariables: '...」つまり子クラス作りも、考えてみたらただの近道
Smalltalk の場合は、字面では将来のスーパークラスに当該作業が委譲されてしまっているので、ここでの(私の脳内の)話の流れ的にはちょっとツライものを端的に露呈してしまっていますが(^_^;)。まあ、これも通常のインスタンスの例と同様に、クラスを作るためにメタクラスにメッセージを送ろうにも、まだメタクラスすら存在しない…ということでやむを得ず次の候補である(将来の)スーパークラスに…という理屈で勘弁してください。<特にツッコミはないようですが念のため。--sumim
>メタクラスに特定のクラスを作らせ、それを自分の子クラスだと認知する、という処理。
Smalltalk に限っては、クラスはメタクラスのシングルトンで、さらに子クラス(「クラス in クラス」の意味で使われているのですよね?)という概念がないので、それは違います。私の理解が正しければ Ruby もそう(クラスはメタクラスのクラス in クラス)ではないですよね? それとも、子クラスとはメタクラスのインスタンスのことですか? それはそれでクラスメソッドのほうのしくみが分からなくなりますが。--sumim
>クラスの(メタ)クラスを引っ張ってきて、それにインスタンス(=クラス)を作らせ、そこにdefする
ええと、Rubyは、self.classのサブクラスを作り、そいつを無名のままにしておいて、selfのclassを元のself.classじゃなくその無名クラスに差し替える、
ってことをやってる(らしき)わけでして。
>Ruby のクラスは(かならずしも)シングルトンではない
何に対して「シングル」だという話でしょうか?
もともとシングルトンを議論するときには、名前空間みたいなものをどう定義するかって話が欠かせない、と記憶してます。
SmalltalkならImageが名前空間である(リモートと繋がない限り)とか、ね。
で、Rubyの特異クラスは無名なので、シングルもへったくれもないはずです。
一般的に、普通の言語(?)のクラスの位置付けは、せいぜい「或る名前空間の中の1つの名に対してシングルだ」としか言えないはずです。
…てゆーか、こういう状況に置かれたモノを「シングルトン」と呼ぶんでしたっけ?なんか違うような…
ん。それとも、クラスに対応するメタクラスに対してシングル、という話ですか?
それなら判りますが、特異クラスが元クラスとメタクラスを共有してるかどうかは(俺は)未確認です。
>Ruby は特異メソッドで、せめてクラスメソッドだけはそのシンプルさにすがろうとした
というか、Rubyに見慣れると、逆にSmalltalkのような(動的かつクラスベースの一般的(?)な)言語では、
「クラスメソッド」ってどうやってるんだ?というのが不思議な気がしてきます。
クラスメソッド定義の記述は、それこそメタクラスにメソッド定義をさせる処理の近道に過ぎないんじゃないの?とか。
--戯
>特にツッコミはないようですが
まだ書いてないだけです。
#ペース早すぎ…
#それに、突っ込みの全てを、対象の文を見た瞬間に思いつくわけではないので…
ちなみに突っ込むならば、必要なメタクラスオブジェクトが「見えない所で」作られてる可能性を無視して良いかどうかは、
俺がまだSmalltalk(Squeak?)の挙動をよく理解していないという意味で、俺が判ってないだけです。
もし有るならば、そいつに処理をさせれば済む。
>子クラス(「クラス in クラス」の意味で使われているのですよね?)
NO。「継承」における子孫クラスです。
- ええい。具体的な言葉(と概念の使い方が一致してるとは限らない複数のプログラム言語)しか無いと、ものごとを表現するのが至極面倒だ…
>クラスに対応するメタクラスに対してシングル、という話ですか?
そうです。
>何に対して「シングル」だという話でしょうか?
シングルトンと言えば、シングルトンです(^_^;)。インスタンスがひとつしか存在しない状態、もしくはそれを保つための機構です。
>もし有るならば、そいつに処理をさせれば済む。
言わんとするところがぜんぜん分からないのですが(^_^;)、いちおう関連するかもしれないので説明しておくと。Smalltalk ではクラスのクラスはメタクラスで、メタクラスのクラスはメタメタクラスです。将来スーパークラスになるクラスはくだんの「subclass: #Hoge instanceVariableNames: '...」というメッセージを受け取ると、(紆余曲折ありますが端的には)まず、メタメタクラスに Hoge class 、つまり Hoge のクラス、メタクラスをそのインスタンスとして作らせます。そして、Hoge class にそのインスタンスである Hoge を作らせるわけです。
クラスはメタクラスのシングルトン、メタクラスはメタメタクラスのインスタンスであることは自明なので、こうしたマクロ的処理がエンドユーザーが意識しないところでなされるという点では、Ruby のクラスメソッド定義時に無名クラスとの置き換えが暗に行なわれるのと似ていますね。--sumim
>シングルトンと言えば、シングルトンです(^_^;)。インスタンスがひとつしか存在しない状態、もしくはそれを保つための機構です。
あー。誰から見て「ひとつ」なのかを考えないと、(特定の状況はさておき)一般論としては無意味です。
allInstancesの「all」って何よ?と以前言ったのと同じココロです。
- 蛇足ですが例えばJavaでWebアプリ(Servlet)するときに悩むのがコレでして、
「アプリに対してシングル」である(べき)ものとか、「ログイン単位に対してシングル」であるべきものとか、
まあ色んなパターンが出てきます。
- 素朴な意味でシングルトンと言ってしまうと、たぶんそれはVMプロセスに対し1つという意味でしょうけど、デスクトップ(いやな言葉だが)な奴ならともかく、サーバみたいに色々な単位が同居せざるを得ない場だとその辺を細かく考えずにいられません。
- たとえば、あるユーザが自分用のwebアプリ(のクラス)をサーバVMにInstallしたら、そのクラスは他人から見えるべきなのか?とか。
- 巷のwebサーバ環境提供プロバイダを構築するとかいう状況なら、他人から見えるのはアウトですね。契約単位またはwebアプリ単位で、他と干渉しないようにする必要がある。
>Hoge class にそのインスタンスである Hoge を作らせる
俺が言いたかったのも正にソレです。
--戯
>一般論としては無意味
出たよ…(^_^;)>戯節 戯さんの脳内“一般”はともかく、私の脳内“一般”においては、あらためていうまでもなくオブジェクト指向とデザインパターンをかじったごく一般の人においても、特に断りがなければ、シングルトンと言えばクラスに対してインスタンスがひとつしか存在しない状態やそれを実現する機構、適用すべきパターン呼称を指すものだと思っていましたが、認識違いですかね。現在の話の流れに限っていえば、サーブレットやプロセスの話をしているわけでもなし。--sumim
>シングルトンと言えば、シングルトンです(^_^;)。インスタンスがひとつしか存在しない状態、もしくはそれを保つための機構です。
もーっちょっと細かく言うと。
インスタンスが「そのVMプロセス(OSから見て:嫌な言葉だが)」に1つしかない状態を保つ、だと、
縛りがきつすぎることが有るわけです。
上記のようなwebアプリ単位とかログイン単位とか、で1つにしたいこともある。
ん?そういう場合はシングルトンとは呼ばないんでしょうか?
てか、呼ばないとすると、それは素朴というか「使えない」定義だな、と思う。
クラスがインスタンスを産み落とす「場」が(少なくともそのクラスから見て)1つしかない、と
決め打ちしてるんですよね。それってどうよ?
#もちろんあらゆる場面において「使えない」わけではないです。
#前述のサーバの例みたいな状況だと「使えない」というだけで。
#「環境」が複雑化すれば、避けて通れない問題になるはず。
そういう意味では、元に戻って考えると、「クラス」変数ってのも素朴な考え方ですね。
そのクラスの状態を置く場が1つしかないと決め打ちしてるんですから。
ちなみに実用的によくやる手が、Dictionaryを作って「場」をKeyにする、って奴です。
そうすれば、不恰好だけど一応、「場」ごとに違うモノを持たせられる。
#ちょっと違うが:
#Rubyのクラス変数は、継承の親も子も「同じ」変数を共有してしまい、親と子で別の値を持たせるってのが出来ない。
#そこで、クラス変数にはHash(Dict)を入れておき、クラス自体をKeyにして所望の値をValueにする、って手をよく使う。
##ReadOnlyな値ならば、クラスメソッドをOverrideするほうが話が早いが…
>現在の話の流れに限っていえば、サーブレットやプロセスの話をしているわけでもなし。
そんなにsumim節と呼んで欲しいならばそれはそれですが:-)、それはともかく…
話の流れ(笑)としては、「何が「場」なのかがよく(俺には)判らない」
という状況(を引っ張った話)だったから、
同じように「場って何?」と悩む状況の例を(ついでに)説明したのですけども。 --戯
話のScopeを勝手に変えるな、ということでしょうか?
だったら、Smalltalkの「当たり前」に疎い俺と、詳しいsumimさんの間では、
明示的な約束や連絡が無い状態でScopeを一致させ続けるのは困難じゃないか、と思いますと一筆。
#というか、そもそもシングルトンのページを作るのが先決かな。
シングルトンは、いまや(というか、そう呼ばれて知られるようになったもとから)別段 Smalltalk 専用の特別な用語ってわけでもないですよ。メソッドが仮想関数の Smalltalk 発祥の呼び名だと言うと「これだから Smalltalk 厨は…」と怒り出す人もいるように、逆にシングルトンが Smalltalk 発祥だということすら知らない人のほうが多いのではないでしょうか。だから、わざわざ説明の必要はないと思いました。ご心配の Smalltalk の「当たり前」 については、気づく範囲で説明を加えるようにしているつもりです。そんなの無意味、sumim節だと戯節全開で話を発散させられるパターンの繰り返しにかなり懲りたので、今後はそうするかどうはわかりませんが。
- おそらく近い将来、特異メソッドも(すでに、CLOS の eql スペシャライザ付き総称関数や Self のメソッドを想定していると思われるコンテキストで特異メソッドと称する人もいるみたいですから、それから察するに)Ruby 発祥とは忘れさられて、インスタンス特異的なメソッドに対する呼称として用いられるようになるのではないでしょうか。
本題の特異メソッドに関する話題が余談になってしまうこの話の展開っていったい…(^_^;)。
- …と思ったので、ここまでのやりとり、移動しました。
--sumim
移動ついでに読み直してみると、戯さんもすでにそれに近いことをおっしゃっておられるように、
- オブジェクトに対するメッセージ送信というメタファをドグマとして(あるいはこのメタファに限らず単にルールをシンプルに保つことを)大事にするか
- (メタファは踏襲しつつ)ALGOL 系記法や C などではぐくまれたプログラミングスタイルに慣れた人をいかに驚かせないか、
という配慮の多少(Smalltalk も、いってもかなり ALGOL 系記法を意識した部分がありますから)の違いに過ぎなくて“シンプルか否か”ということに関しては平行線をたどりそうですね。
そして、クラスにメソッドはいらないという戯さんは、頭の中では前者を尊重しつつも、基本的なスタンスはメッセージ送信メタファをあまりに突き詰めてしまうと(私には Smalltalk をしても、まだ踏み込みが足りないくらいなのですが…(^_^;))ビビってしまうたぐいの後者であるのかな、と。--sumim
>シングルトンは、いまや(というか、そう呼ばれて知られるようになったもとから)別段 Smalltalk 専用の特別な用語ってわけでもないですよ
>逆にシングルトンが Smalltalk 発祥だということすら知らない人のほうが多いのではないでしょうか。
そうじゃなく(そんなことはどうでも良くて)、
シングルトンという概念を「クラスにインスタンスが1つ云々」と
素朴に定義出来るのは、 Smalltalk(など)に限った話だなあ、ということです。
「OOPという語の世間での解釈」(カプセル化、継承、多態性とか)に辟易してる人(^^;なら
悩みを判ってくれそうなもんだと思ったんだがなあ。
個々の例えばシングルトン自体に対する悩みを気付くかどうかはどうでもいいんだが、
「そういう悩みの種類がある」ことは判って欲しく。
>戯さんの脳内“一般”はともかく、私の脳内“一般”においては、あらためていうまでもなくオブジェクト指向とデザインパターンをかじったごく一般の人
「一般」ってコトバは、多数決(か、皮肉としてその対極である"俺定義")を表現する言葉じゃない、と記憶していますが。
OOPでいう汎化の概念みたいなもののことだったのでは…
>Ruby 発祥とは忘れさられて、インスタンス特異的なメソッドに対する呼称
ええと?それ、何かが不味いんですか?
少なくとも「インスタンス特異的なメソッドに対する呼称」なら、不味い解釈だとは聞こえないんですが?
#ところで、Ruby発祥だという話は俺は気付いてなかったんですが、ソースどこに有りましたか?
矮小な解釈に変貌していくなら俺としても嫌ですが、より的を得た解釈になら幾らでも変貌して欲しいな。
そしてそれがイツかRubyでの定義を「超えた」ものになるなら、もっと素晴らしい。
その暁には、元のRubyでの定義をこそ「サブセット」だと呼べば良い。
「SmalltalkのOOP」を(少なくとも俺が)支持出来る理由は、
それが正統(オリジナル)だからじゃなく、
それが正当だ(と少なくとも俺にゃ思える)から、です。
>基本的なスタンスはメッセージ送信メタファをあまりに突き詰めてしまうと(私には Smalltalk をしても、まだ踏み込みが足りないくらいなのですが…(^_^;))ビビってしまうたぐいの後者
待て待て。
「メッセージメタファドグマが好きか」と「それをALGOLくさい文法にMapする(と嬉しがる)か」とは
別問題だ(と俺は思う)って言ってるじゃん(T_T)
「メッセージ送信メタファ」というコトバの必要条件として特定の文法形態であることをも含めるかどうか、は
それこそ話が平行線になっているわけですが、逆にいえば平行なのはそこだけじゃないかな?
>クラスにメソッドはいらないという戯さん
あれ?そんなこと言ったっけ俺?
「クラス変数どうよ?」とは言ったし、
「クラスなんてオブジェクト2個(^^;有れば出来るじゃん」は上記のページ(ばぶばぶ(要するに素朴なプロトタイプベース嗜好))での主張ですが。
あ。あれか。>「そもそもクラスメソッドという考え方自体が妙」
あれは「クラスだってオブジェクトなんだから、わざわざ「クラスメソッド」と称する枠組みを考える必要は無いじゃん」
という意味です。
Smalltalkのクラスブラウザで言えば、見えるのがインスタンスメソッドかクラスメソッドかを選ぶボタンは不要かも、という話。
HogeクラスじゃなくHogeClassクラスの(インスタンス)メソッドを見れば済むわけで。
あのボタンが有るのは正に利便性(近道)のためですよね。
だとすれば、クラスメソッドを「クラスの特異メソッド」としてるRubyと、五十歩百歩では?と。
あと、それとメッセージメタファ云々とは無関係じゃないかな?
ここでの話のあるべき中心は恐らく「クラス(だけ)が(インスタンスのための)メソッドの置き場である(と思いたい)か否か」であって、
文法とかALGOLとかはまた別の話題じゃないかな…
#このページ名は、つまりそういう議論を「したい」という意思表示だったのでは?
#つまり、重んじるべきは話の流れよりはページ名なんじゃないのかな?
んー。「Smalltalkから何を奪っても(あるいは何を足しても)まだOOP言語として許せるか?」ってのを聞いてみると面白いかも知れない。
まあ、それ以前に「OOP言語から何を奪ってもまだOOP言語として許せるか?」っていう問題が有るかな… --戯
「そもそもクラスメソッドという考え方自体が妙なんじゃないか」つーの同感。
クラスメソッドだけでインスタンスのないユーティリティクラスって何よ。
クラスを名前空間の代わりに使ってるだけでは? --とおりすがり
Smalltalk ではクラスもオブジェクトで、しかも無名クラスというのがなく常に名前があるので、名前が付いたオブジェクトとして扱うと便利なのでしょう。--sumim
このページを編集 (21044 bytes)
|
以下の 1 ページから参照されています。 |
- 特異クラス 最終更新: 2003-12-30, 00:37:52 <p2031-f>
This page has been visited 7102 times.