1 名前:デフォルトの名無しさん [03/12/08 21:30] オブジェクトを複製または継承によって生成を行う言語, プロトタイプベース・オブジェクト指向言語について語りましょうよ. 関連リンク >>2
405 名前:デフォルトの名無しさん mailto:sage [04/02/06 14:08] でもクロージャでオブジェクト作るの結構メンドイんだよな.
406 名前:デフォルトの名無しさん mailto:sage [04/02/06 17:00] >403 、ミ川川川彡 ,ィr彡'";;;;;;;;;;;;;;; ミ 彡 ,.ィi彡',.=从i、;;;;;;;;;;;; 三 ギ そ 三 ,ィ/イ,r'" .i!li,il i、ミ',:;;;; 三. ャ れ 三 ,. -‐==- 、, /!li/'/ l'' l', ',ヾ,ヽ; 三 グ は 三 ,,__-=ニ三三ニヾヽl!/,_ ,_i 、,,.ィ'=-、_ヾヾ 三 で 三,. ‐ニ三=,==‐ ''' `‐゛j,ェツ''''ー=5r‐ォ、, ヽ 三. 言 ひ 三 .,,__/ . ,' ン′  ̄ 三 っ ょ 三 / i l, 三. て っ 三 ノ ..::.:... ,_ i ! `´' J 三 る と 三 iェァメ`'7rェ、,ー' i }エ=、 三 の し 三 ノ "'  ̄ ! '';;;;;;; 三 か て 三. iヽ,_ン J l 三 !? 三 !し=、 ヽ i ,. 彡 ミ ! "'' `'′ ヽ、,,__,,..,_ィ,..r,',", 彡川川川ミ. l _, , | ` ー、≡=,ン _,,, ヽ、 _,,,,,ィニ三"'" ,,.'ヘ rー‐ ''''''" `, i'''ニ'" ,. -‐'" `/ ヽ ! i´ / ノレ'ー'! / O
407 名前:デフォルトの名無しさん mailto:sage [04/02/07 00:08] このスレではプロトタイプベースの作り方なんて話も OK なんですか? 辞書でも用意して、名前と値をぽんぽん追加してくだけでいいんかな。
408 名前:1 mailto:sage [04/02/07 20:15] >>407 クラスベースでプロトタイプベースを実現する方法ですか? それともプロトタイプベース言語の実装方法? どっちにしても興味深いですね.
409 名前:デフォルトの名無しさん mailto:sage [04/02/07 22:05] え、そうかな。基本的にハッシュでも用意して名前に対応する値や関数を 突っ込むだけでしょ?で、オブジェクト複製用のオペレータがあれば 一応プロトタイプベースデキタ!くらいならスクリプト系言語なら簡単に できません?他にも何かいるのかな?
410 名前:デフォルトの名無しさん mailto:sage [04/02/07 22:16] >>409 委譲機構
411 名前:デフォルトの名無しさん mailto:sage [04/02/07 22:25] 委譲するオブジェクトのリストでも持っといて、自分のスロットに 見つからなかったらそっちから順番に検索…とかじゃ駄目っすかね?
412 名前:n [04/02/08 00:08] class Proto attr_accessor :slot,:proto,:mixin def initialize; @slot = Hash.new; @proto = nil; @mixin = Array.new; end def inherit; obj = Proto.new; obj.proto = self; return obj; end def call(key); if @slot.key?(key) then @slot[key].call else self.proto.call(key) end;end def set(key,val); @slot[key]=val; end def get(key)@slot[key]end end foo = Proto.new foo.set "foo",proc{puts"foo"} foo.set "hello",proc{puts"Hello,Foo!"} bar = foo.inherit bar.set "bar",proc{puts"foo"} bar.call("foo") bar.call("hello") hoge = bar.inherit hoge.set "hello",proc{puts"Hello,Hoge!"} fuga = hoge.inherit fuga.call("foo") fuga.call("hello") foo.call("hello") こんな感じですか?
413 名前:デフォルトの名無しさん mailto:sage [04/02/08 00:10] なにが?
414 名前:デフォルトの名無しさん mailto:sage [04/02/08 00:20] >>3-4 聞いたこともない言語ばかりだなぁ
415 名前:デフォルトの名無しさん mailto:sage [04/02/08 03:23] >>411-412 たとえば、call でそのメソッドを起動したとき、レシーバの get "foo" が "foo" なら "yes"、 そうでなければ "no" と答える "is_foo?" というメソッドスロットを foo に追加できますか?
416 名前:デフォルトの名無しさん mailto:sage [04/02/08 03:53] 追加される proc の側で追加先のオブジェクトを参照できる必要があるね。 python みたいに proc の引数に明示的に self 相当のものが。
417 名前:デフォルトの名無しさん [04/02/08 06:21] >>405 それは、ひょっとしてギャグで言ってるのか!? >>406 意味不明過ぎ。
418 名前:デフォルトの名無しさん [04/02/08 06:34] なんかポインター見失っちゃったんだけど、 Squeak上で動くSelfとか、Smalltalk無しで動くSelfとか、 Sunの研究部門が数年前に出してたっけ?もしかして。
419 名前:デフォルトの名無しさん [04/02/08 06:42] あ、Self 4.1〜4.2が1,2年前に出たのか。 10年近く前に探しに行った時は、 ・Smalltalk VMが必要なバージョンとか、 ・Sparc上で動くバイナリしかなくて、 ダウンロードしても実行に困った覚えがあったっけ。 今はMac上に移植されてるのか。おまぃら、いい時代に生きてますね research.sun.com/research/self/ -------------------------------------------------------------------------------- Self 4.2 Self 4.2 is the most recent public release (June 2003). It features the optimizing compiler on the PowerPC. Jump here to find out more. -------------------------------------------------------------------------------- Self 4.1 Self 4.1.6 was the most previous public release (September 2002). It runs on the Macintosh as well as on machines from Sun Microsystems, Inc. Jump here to find out more. -------------------------------------------------------------------------------- Self 4.0 Self 4.0 was a previous public release (July 1995). Jump here to find out more.
420 名前:デフォルトの名無しさん mailto:sage [04/02/08 13:07] Pythonってクラスベースに入るの? classといってもオブジェクト生成関数みたいなもんだよね?
421 名前:デフォルトの名無しさん mailto:sage [04/02/08 13:15] > Pythonってクラスベースに入るの? Yes. > classといってもオブジェクト生成関数みたいなもんだよね? Yes. ところでPythonはインスタンス固有のメソッド(Rubyでいう特異メソッド) を作れるのに、多分誰も利用してませんね・・・。
422 名前:420 mailto:sage [04/02/08 13:24] >>421 俺は結構使ってる.だからクラスベースって言われるのに違和感があった. こういうのもクラスベースに入るんだね.
423 名前:n [04/02/08 14:54] >> 415 class Proto attr_accessor :slot,:proto def initialize; @slot = Hash.new; @proto = nil end def inherit; obj = Proto.new; obj.proto = self; return obj end def call(key,*arg) if @slot.key?(key) then return @slot[key].call(self,*arg) else obj = self while obj = obj.proto; if obj.slot.key?(key) then return obj.slot[key].call(self,*arg) end end end end def set(key,val); @slot[key]=val; end def get(key)@slot[key]end end foo = Proto.new foo.set "foo","foo" foo.set "is_foo?",lambda{|this|this.get("foo") == "foo" ? "yes" : "no"} puts foo.call("is_foo?") #=>"yes" bar = foo.inherit bar.set "foo","bar" puts bar.call("is_foo?") #=>"no" ちょっと強引ですが、こうすればレシーバのメソッドも呼べます。
424 名前:デフォルトの名無しさん mailto:sage [04/02/08 16:35] >>423 乙。bank_account を組んでみました。 bank_account = Proto.new bank_account.set "get_balance", proc{|this| this.get "balance"} bank_account.set "set_balance", proc{|this, x| this.set "balance", x} bank_account.call "set_balance", 200 bank_account.set "deposit", proc{|this, x| this.call "set_balance", (this.call "get_balance") + x} bank_account.call "deposit", 50 => 250 bank_account.set "withdraw", proc{|this, x| this.call "set_balance", [0, (this.call "get_balance") - x].max} bank_account.call "withdraw", 100 => 150 bank_account.call "withdraw", 200 => 0 my_account = bank_account.inherit my_account.call "set_balance", 100 => 100 my_account.call "deposit", 50 => 150 my_account.call "withdraw", 100 => 50
425 名前:デフォルトの名無しさん mailto:sage [04/02/08 16:36] >>424 続き、 stock_account = bank_account.inherit stock_account.set "get_num_shares", proc{|this| this.get "num_shares"} stock_account.set "set_num_shares", proc{|this, x| this.set "num_shares", x} stock_account.call "set_num_shares", 10 stock_account.set "get_price_per_share", proc{|this| this.get "price_per_share"} stock_account.set "set_price_per_share", proc{|this, x| this.set "price_per_share", x} stock_account.call "set_price_per_share", 30 stock_account.set "get_balance", proc{|this| (this.call "get_num_shares") * (this.call "get_price_per_share")} stock_account.call "get_balance" => 300 stock_account.set "set_balance", proc{|this, x| this.call "set_num_shares", Float(x) / (this.call "get_price_per_share") this.call "get_balance"} stock_account.call "deposit", 60 stock_account.call "get_num_shares" => 12.0
426 名前:デフォルトの名無しさん mailto:sage [04/02/08 21:12] >>421-422 どうやって作るの?データは簡単に作れるけどメソッドの追加ができん……
427 名前:デフォルトの名無しさん mailto:sage [04/02/08 21:14] まったくPythonは素晴らしいね。 Rubyとかいう出来損ないの言語とちがって。
428 名前:デフォルトの名無しさん mailto:sage [04/02/08 21:22] 荒れるからやめれ。
429 名前:デフォルトの名無しさん mailto:sage [04/02/08 21:48] ヤバイ。 Ruby ヤバイ。まじでヤバイよ、マジヤバイ。Ruby ヤバイ。 まずオブジェクト指向。もうただのオブジェクト指向なんてもんじゃない。純粋オブジェク指向。 オブジェクト指向といとかっても「基本型は別なんでしょ?」とか、もう、そういうレベルじゃない。 何しろ全部オブジェクト。スゲェ!なんか特別扱いとか無いの。数値も文字列も全部オブジェクト。 <!-- しかも他の言語をリスペクトしてるらしい。ヤバイよ、(パク)リスペクトだよ。 だって普通は他の言語をリスペクトしといて機能取り込んだ後叩くとかしないじゃん。 だってリスペクトしたって事はどっちかっつーと恩があるわけじゃん。 リクペクトしといてあとてやーいやーいザマーみろとか言わないっしょ。だから普通はリスペクト元の言語貶したりしない。話のわかるヤツだ。 けど Ruby はヤバイ。そんなの気にしない。貶しまくり。 他言語から心底ウザがられても「悔しがってる」「負けおしみですか?」とかよくわかんないくらい信者強気。ヤバすぎ。 --> オブジェクト指向っていったけど、もしかしたらオブジェクト指向が最後のパラダイムかもしんない。でも最後って事にすると 「じゃあ、Ruby 最強?」 って事に<!-- 信者の脳内では-->なるし、それは誰も止められない。ヤバイ。誰にも止められないなんて凄すぎる。 あと超ユーザビリティ高い。end で終るから。shift 押さなくて良いんだって。ヤバイ。凄すぎ。括弧は最悪インデントは基地外。怖い。 それに超拡張モジュール書きやすい。GC のおかげらしい。参照カウントとかすると拡張モジュール内でその辺気にしなきゃいけないじゃん?でも Ruby は平気。C スタックとか平気でスキャンしてくれる。C スタックて。小学生でも直接操作しねぇよ、最近。 でも Ruby は全然平気。 C を C のまま扱ってる。凄い。ヤバイ。 とにかく貴様ら、Ruby のヤバさをもっと知るべきだと思います。 そんなヤバイ Ruby で作られたアプリケーションとか超偉い。もっとがんばれ。超がんばれ。
430 名前:デフォルトの名無しさん mailto:sage [04/02/08 21:58] コピペ厨キターーー微妙に主旨がバラバラな内容なのがヘタレだな
431 名前:デフォルトの名無しさん mailto:sage [04/02/08 22:12] 先日Rubyを齧ってみました。 確かにうんこの味がしました。 Rubyはうんこです。 間違いありません。 Rubyなんて大層な名前はやめて、○んこと改名すべきです。
432 名前:デフォルトの名無しさん mailto:sage [04/02/08 22:23] 簡単、軽量に実装できるからNewtonみたいなのも採用出来たんでしょうね。
433 名前:デフォルトの名無しさん mailto:sage [04/02/08 22:56] >>426 421-422 じゃないけど、Python 学習をかねて調べてみました。 class Foo: def f(self): return "I'm of class" foo = Foo() foo.f() => "I'm of class" bar = Foo() bar.f() => "I'm of class" def newF(): return "I'm *not" of class" foo.f = newF foo.f() => "I'm *not* of class" bar.f() => "I'm of class" def anotherF(self): return "I'm *also* of class" Foo.f = antoherF foo.f() => "I'm *not* of class" bar.f() => "I'm *also* of class"
434 名前:426 mailto:sage [04/02/08 23:07] >>433 それではただ関数を入れてるだけではないか。 漏れの求めるメソッドは↓で言うところの呼び出し時の冗長な obj を省ける いわゆるメソッドが追加できるのか調べているのだが…。 class Object: pass obj = Object(); def say(self, msg): print msg obj.say = say print obj.say obj.say(obj, "hello") # obj ウザー obj.say(obj, "humm") # ウザー
435 名前:デフォルトの名無しさん mailto:sage [04/02/09 13:48] >>426 newモジュールを使うナリよ。
436 名前:デフォルトの名無しさん mailto:sage [04/02/10 21:14] >>435 スマソ低能なのでマニュアル見たんだが良くわらん.サンプルキボンヌ
437 名前:デフォルトの名無しさん mailto:sage [04/02/10 22:43] 426がちゃんと読んでないだけかと思われ
438 名前:デフォルトの名無しさん mailto:sage [04/02/11 01:18] >>435 そうなりか! さんくす Python 学習を兼ねて、調べて書いてみました。 import new class Obj: def m(self): print "method of " + self.__class__.__name__ obj1 = Obj() obj1.m() => 'method of Obj' obj2 = Obj() obj2.m() => 'method of Obj' def m(self): print "method *not* of " + self.__class__.__name__ obj2.m = new.instancemethod(m, obj2, Obj) obj2.m() => 'method *not* of Obj' obj1.m() => 'method of Obj' obj3 = Obj() obj3.m() => 'method of Obj'
439 名前:デフォルトの名無しさん mailto:sage [04/02/11 15:46] うぉ.格好悪い書き方だなぁ.これってクラスベースだからなのか, Python固有の問題なのかどっち?
440 名前:デフォルトの名無しさん mailto:sage [04/02/11 16:08] instancemethodが使えるのは後付けだからなぁ・・・。 クラスベースだからでもあり、Pythonだからでもあり。 本格的に使用するもんじゃないと思われ。
441 名前:デフォルトの名無しさん mailto:sage [04/02/11 20:16] うーん.確かに,あんまり使う気は起きないなぁ. ちょっと残念.
442 名前:デフォルトの名無しさん mailto:sage [04/02/11 23:37] >>438 参考までにほぼ同様のことを Ruby と CLOS で、 class Obj def m; p "method of " + self.class.name; end end obj1 = Obj.new obj1.m => "method of Obj" obj2 = Obj.new obj2.m => "method of Obj" def obj2.m; p "method *not* of " + self.class.name; end obj2.m => "method *not* of Obj" obj1.m => "method of Obj" obj3 = Obj.new obj3.m => "method of Obj"
443 名前:デフォルトの名無しさん mailto:sage [04/02/11 23:39] (defclass <obj> () ()) (defmethod m ((self <obj>)) (print (concatenate 'string "method for an ordinary " (string (class-name (class-of self)))))) (setq obj1 (make-instance '<obj>)) (m obj1) => "method for an ordinary <OBJ>" (setq obj2 (make-instance '<obj>)) (defmethod m ((self (eql obj2))) (print (concatenate 'string "method *not* for an ordinary " (string (class-name (class-of self)))))) (m obj2) => "method *not* for an ordinary <OBJ>" (m obj1) => "method for an ordinary <OBJ>" (setq obj3 (make-instance '<obj>)) (m obj3) => "method for an ordinary <OBJ>"
444 名前:デフォルトの名無しさん mailto:sage [04/02/12 00:45] Squeak の workspace で無理矢理おなじようなことを。 Object subclass: #Obj instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Category-Name'. Obj compile: 'm ↑''method of '', self class name' classified: nil. obj1 ← Obj new. obj1 m => 'method of Obj' obj2 ← Obj new. obj2 m => 'method of Obj' obj2 assureUniClass. obj2 class compile: 'm ↑''method *not* of '', self class name' classified: nil. obj2 m => 'method *not* of Obj1' obj1 m => 'method of Obj' obj3 ← Obj new. obj3 m => 'method of Obj' ただし、この時点で、 obj1 class == obj2 class. => false obj2 class superclass == obj1 class => true obj1 class == obj3 class. => true
445 名前:デフォルトの名無しさん mailto:sage [04/02/12 02:01] ちなみに Self だとこんなかんじ。 globals _AddSlots: (| obj. obj1. obj2. obj3 |) obj: (| name <- 'obj'. m = (^ 'method of ', parent name) |) obj1: (| parent* = obj |). obj1 m => 'method of obj' obj2: (| parent* = obj |). obj2 m => 'method of obj' obj2 _AddSlots: (| m = (^ 'method *not* of ', parent name) |). obj2 m => 'method *not* of obj' obj3: (| parent* = obj |). obj3 m => 'method of obj' ただしここで obj は、クラス(or トレイト)っぽい位置づけ。
446 名前:デフォルトの名無しさん mailto:sage [04/02/12 03:06] 内部的には Python は CLOS に、Ruby は Smalltalk/Squeak の それに近いのかな…。つまり、CLOS 、Python はインスタンスと そのクラスとの関係には手を付けずに、注目するインスタンス専用の メソッドを用意する。これに対して、Ruby (と、まあ Smalltalk/ Squeak)では元のクラスのサブクラスを作って、注目するインスタンス のクラスをそれに差し替え、インスタンス特異的なメソッドは差し替え たサブクラスに定義している。 ちなみに Ruby は構文の工夫や、無名クラスを明示的にしないことで、 さもインスタンスにそれ特異的なメソッドを追加できているように 見せかけているので、ユーザーには
447 名前:デフォルトの名無しさん mailto:sage [04/02/12 11:24] どうした >>446 ! 何があったんだ! どうも concatenate とか本質的でないとこで長くなってる気がするので CLOS 版は format つかって文字列返すくらいにしといたほうがいいのでは? (defclass <obj> () ()) (defmethod m ((self <obj>)) (format nil "method for an ordinary ~A~%" (class-name (class-of self)))) (setq obj1 (make-instance '<obj>)) (m obj1) => "method for an ordinary <obj>" (setq obj2 (make-instance '<obj>)) (defmethod m ((self (eql obj2))) (format nil "method *not* for an ordinary ~A" (class-name (class-of self)))) (m obj1) => "method *not* for an ordinary <obj>" かつて Lisp 方面で CLOS ダメポプロトタイプベースイイ! って言ってた連中って GUI ならプロトタイプのほうが自然だ ! とかプロトタイプベースのほうが速い! とか言っ てたような記憶があるのです.やっぱ速いんですかね?
448 名前:デフォルトの名無しさん mailto:sage [04/02/12 11:44] >>447 書きかけで送っちゃったけど、意味は通じるからいいかなと(笑)。 format はたしかにそうです。馴染みのないひとにも対応付け易い よう、冗長にしてみました。ご指摘 & 実例たーしゃ。 ついでに Self も parent* スロットには暗示的にアクセスするので、 こちらも parent name などとする必要はなく、単に name だけに すべきです。
449 名前:デフォルトの名無しさん mailto:sage [04/02/12 14:33] >>446 > メソッドを用意する。これに対して、Ruby (と、まあ Smalltalk/ > Squeak)では元のクラスのサブクラスを作って、注目するインスタンス > のクラスをそれに差し替え、インスタンス特異的なメソッドは差し替え > たサブクラスに定義している。 > 12ヘェ〜。純粋クラスベースOOの枠組み内でうまいことやってるですね。 ちなみにPythonが冗長なのは、滅多に使わないような機能や生産性にほとんど 影響しないようなところに安易に新しい構文を用意することで、言語が無駄に 複雑化したり初心者を混乱させたりするのは悪である、という思想があるから のようです。ってプロトタイプとかけ離れてきたのでこの辺で。
450 名前:デフォルトの名無しさん mailto:sage [04/02/14 16:30] sof.ch/dan/qscheme/intro.html > Experimental prototype base object orientation. Scheme 処理系の一つ、QScheme はプロトタイプベースなオブジェクトシステムを 持ってるらしい。
451 名前:デフォルトの名無しさん mailto:sage [04/02/15 17:36] 結構みんなこのスレ見てるんだね。今日だけでも色んなスレでプロトタイプベースという 言葉を見たよ(以前はそうでもなかったけど)。それともプロトタイプベースの認知度が 上がったのかな。
452 名前:デフォルトの名無しさん mailto:sage [04/02/15 20:59] www.logtalk.org/features.html >Support for both class-based and prototype-based systems >You may have, in the same application, class-based hierarchies (with instantiation >and specialization relations) and prototype-based hierarchies (with extension relations). Prolog のオブジェクト指向拡張ライブラリ? の Logtalk はクラスベースとプロトタイプ ベースの両方をサポートしているみたい。Features 見ていると、色々面白そう。
453 名前:デフォルトの名無しさん mailto:sage [04/02/15 21:04] で、プロトタイプベースの中で、一番進んだ言語って何? Ioですか?
454 名前:デフォルトの名無しさん mailto:sage [04/02/15 21:08] ああ、一番遅れた言語ね。
455 名前:デフォルトの名無しさん mailto:sage [04/02/15 21:23] MLud もプロトタイプベースだけど、強型付けな ML 上に構築されているという事は、 MLud 自身も強く型付けされた環境なのかなぁ。だとしたらちょっと異色かも。 moonflare.com/code/mlud/index.php
456 名前:デフォルトの名無しさん mailto:sage [04/02/15 21:36] >>453 言語に大きく依存した機能じゃないから、好きな言語でどうぞっていう流れじゃないかな。 クロージャがあるか、ファーストクラスのメソッドがあれば何とかなる。
457 名前:デフォルトの名無しさん mailto:sage [04/02/16 00:12] >>453 一番進んでいるのはオブジェクトモデル、VMの性能、クラスライブラリ の充実度のどれをとってもいまだにSelfだろ。ちょっと古いのと、対象 となるプラットフォームが異常に限られているのが玉に瑕だが。 NewtonScript もかなりよくできていたけど、これはプラットフォーム 自体がなくなっちゃったからなぁ…。 目先を変えて、Scheme の SLIB に含まれる YASOS なんかもいいかもしれない。 ttp://members.at.infoseek.co.jp/zzyyb/scm/slib-ja/slib_2.html#SEC35
458 名前:デフォルトの名無しさん mailto:sage [04/02/16 00:20] >>456 インスタンス特異的メソッドのみならともかく、委譲機構をそれなりに 実現しようとすると結構な手間になるのでは?
459 名前:デフォルトの名無しさん mailto:sage [04/02/16 00:55] インスタンスにスロットを持たせるのはなんとなく分かったので、 委譲機構とやらのサンプルコードをキボンヌ。最低限どんな動きが どれくれーできればいいんだ?
460 名前:デフォルトの名無しさん mailto:sage [04/02/16 02:46] >>459 既出ですが、これなんかよく説明されていると思います。 ttp://kumiki.c.u-tokyo.ac.jp/~ichiyama/projects/reports/seruby/ サンプルコードの書き下ろしは面倒なので勘弁してください。 私自身は、簡単にできるとは思っても言ってもいないので、説明責任もないし(^_^;)。 最低限できればよいのは、委譲先オブジェクトのメソッドを暗示的 (レシーバには見つけられないとき)に、あるいは必要なら明示的 (Self の resend、Smalltalk 系の super)に起動できて、その際、起動した メソッドのコード中の偽変数 self には(メソッドホルダではなく) レシーバを束縛できていること、でしょうか。
461 名前:デフォルトの名無しさん mailto:sage [04/02/17 00:33] 459じゃないんだけど。 つまり委譲機構ってのは手前で処理できぬメッセージが来たら プロトタイプチェーンを遡ってメソッドを探す事っつーことですか。 クラスベースだと何に当たる言葉なんだろう。「ポリもアフィズム」じゃないし。 self / this にそもそもメッセージを受けた人が入らないといけないが、 クラスベースなら[[クラスの]]継承階層を遡っていき、クラスとオブジェクトが峻別されるから あまり問題にならないところだが、 プロトタイプベースだと[[オブジェクトの]]チェーンを遡っていくんだが でも親のオブジェクトが受けちゃったりしたらまずいって訳だ。 RubyもSelfもわからんので読めん。 漏れの読めるプロトタイプベースはECMAScriptだけでいいや・・・。
462 名前:n [04/02/17 10:11] 本当にECMAScriptってプロトタイプベースなんですか? わたしにはろくに継承/委譲ができないように思えるのですが・・・。
463 名前:デフォルトの名無しさん mailto:sage [04/02/17 16:56] >>462 勉強を兼ねて恒例の bank account を書いてみました。 委譲/継承も多態もできているみたいです。 個人的には self をメソッドで暗示的引数に指定しなくていいぶん、 Python よりはスジがよいように思います。 <script type="text/javascript"> var bank_account = new Object; function ba_set_balance(_x) {this.balance = _x; return this} bank_account.set_balance = ba_set_balance; function ba_get_balance() {return this.balance} bank_account.get_balance = ba_get_balance; document.write( bank_account.set_balance(200).get_balance() + "<br>"); // => 200 function ba_deposit(_x) { this.set_balance(this.get_balance() + _x); return this} bank_account.deposit = ba_deposit; document.write( bank_account.deposit(50).get_balance() + "<br>"); // => 250 function ba_withdraw(_x) { this.set_balance(Math.max(this.get_balance() - _x, 0)); return this} bank_account.withdraw = ba_withdraw; document.write( bank_account.withdraw(100).get_balance() + "<br>"); // => 150 document.write( bank_account.withdraw(200).get_balance() + "<br>"); // => 0
464 名前:デフォルトの名無しさん mailto:sage [04/02/17 17:05] >>463 続き var my_account = new Object; my_account.__proto__ = bank_account; document.write( my_account.set_balance(100).get_balance() + "<br>"); // => 100 document.write( my_account.deposit(50).get_balance() + "<br>"); // => 150 document.write( bank_account.get_balance() + "<br>"); // => 0
465 名前:デフォルトの名無しさん mailto:sage [04/02/17 17:07] >>464 続き function sa_set_num_shares(_x) {this.num_shares = _x; return this} stock_account.set_num_shares = sa_set_num_shares; function sa_get_num_shares() {return this.num_shares} stock_account.get_num_shares = sa_get_num_shares; function sa_set_price_per_share(_x) {this.price_per_share = _x; return this} stock_account.set_price_per_share = sa_set_price_per_share; function sa_get_price_per_share() {return this.price_per_share} stock_account.get_price_per_share = sa_get_price_per_share; stock_account.set_num_shares(10).set_price_per_share(30); document.write( stock_account.get_num_shares() + "<br>"); // => 10 document.write( stock_account.get_price_per_share() + "<br>"); // => 30
466 名前:デフォルトの名無しさん mailto:sage [04/02/17 17:10] >>465 続き function sa_set_balance(_x) { this.set_num_shares(_x / this.get_price_per_share()); return this} stock_account.set_balance = sa_set_balance; function sa_get_balance() { return this.get_num_shares() * this.get_price_per_share()} stock_account.get_balance = sa_get_balance; document.write( stock_account.get_balance() + "<br>"); // => 300 document.write( stock_account.set_balance(600).get_balance() + "<br>"); // => 600 document.write( stock_account.set_balance(600).get_num_shares() + "<br>"); // => 20 document.write( stock_account.deposit(60).get_balance() + "<br>"); // => 660 document.write( stock_account.get_num_shares() + "<br>"); // => 22 document.write( stock_account.withdraw(90).get_balance() + "<br>"); // => 570 document.write( stock_account.get_num_shares() + "<br>"); // => 19 </script>
467 名前:デフォルトの名無しさん mailto:sage [04/02/17 18:03] 読み難いソースだなぁ…
468 名前:デフォルトの名無しさん mailto:sage [04/02/17 23:48] Netscapeで動く。 IEでは動かない。 セッターが必ずthisを返してメッセージをカスケードさせてるのは趣味? Smalltalk以外でもそうするものなの? Netscapeのガイド ttp://devedge.netscape.com/library/manuals/2000/javascript/1.5/guide/obj2.html#1013803 だと、コンストラクタ作って、prototypeプロパティに継承元をセットしていて、クラスベースっぽい
469 名前:デフォルトの名無しさん mailto:sage [04/02/18 08:51] stock_accountの定義はどこ?? var stock_account = new Object; stock_account.__proto__ = bank_account; が抜けてる??
470 名前:デフォルトの名無しさん mailto:sage [04/02/18 09:36] >>469 ああ、すみません。抜けてます。465 と 464 の間に。 >>468 ああ、すみません。Smalltalker なもんですから…。 そうでないと気持ち悪くて…。 >>467 ああ、すみません。初めて書いた JavaScript なもんですから…。 でも、私の責任は1/3くらいです(^_^;)。 1/3は JavaScript のせい、1/3は2ちゃんの改行数制限せいです(笑)。
471 名前:n [04/02/18 10:21] あう、__proto__を使うのですね、それは反則の方向で(ぇ 確かに__proto__が使えるならプロトタイプベースと呼べるとは思うのですが、 __proto__がなくてもプロトタイプベースなのかなぁ、と感じたのですよ。
472 名前:デフォルトの名無しさん mailto:sage [04/02/19 09:20] >>470 もう少しJSらしく書いてみたけど、普通にやると多態は駄目。 var BankAccount = new Object; BankAccount.balance = 200; document.write(BankAccount.balance + "<br>"); // 200 BankAccount.deposit = function(x) { return this.balance += x; } document.write(BankAccount.deposit(50) + "<br>"); // 250 BankAccount.withdraw = function(x) { return this.balance = Math.max(this.balance - x, 0); } document.write(BankAccount.withdraw(100) + "<br>"); // 150 document.write(BankAccount.withdraw(200) + "<br>"); // 0 function make_Account(){} make_Account.prototype = BankAccount; var myAccount = new make_Account; // Mozilla 系 JS ならば var myAccont.__proto__ = BankAccount だけでもいい。 myAccount.balance = 100; document.write(myAccount.balance + "<br>"); // 100 document.write(myAccount.deposit(50) + "<br>"); // 150 document.write(BankAccount.balance + "<br>"); // 0
473 名前:デフォルトの名無しさん mailto:sage [04/02/19 09:22] 続き var stockAccount = new make_Account; // Mozilla 系 JS ならば var stockAccount.__proto__ = BankAccount でもいい。 stockAccount.numShares = 10; stockAccount.pricePerShare = 30; document.write(stockAccount.numShares + "<br>"); // 10 document.write(stockAccount.pricePerShare + "<br>"); // 30 stockAccount.balance = function(x) { // こんな風にしてみたけど… if(arguments.length) this.numShares = x / this.pricePerShare; return this.numShares * this.pricePerShare; } document.write(stockAccount.balance() + "<br>"); // 300 document.write(stockAccount.balance(600) + "<br>"); // 600 document.write(stockAccount.numShares + "<br>"); // 20 stockAccount.deposit(60); document.write(stockAccount.balance() + "<br>"); // Error: stockAccount.balance is not a function document.write(stockAccount.numShares + "<br>"); stockAccount.withdraw(90); document.write(stockAccount.balance() + "<br>"); document.write(stockAccount.numShares + "<br>");
474 名前:デフォルトの名無しさん mailto:sage [04/02/19 09:29] stockAccount.deposit(x) でこける。 sumim.no-ip.com:8080/wiki/809 の Io の最初の例と同じで # つか、上自体 Io の例そのままパクッただけだったり。 既にあるプロパティと同名のメソッドを作れない。 結局 getter, setter になるメソッドを書かないとうまくいかない。
475 名前:デフォルトの名無しさん mailto:sage [04/02/19 10:52] ついでにhomepage.mac.com/mkino2/oop/chainOfResp/index.html の Chain of Responsibility を JS で。 var app = new Object; app.preview = function(){alert("preview in app");} function make_app(){} make_app.prototype = app; var dialog = new make_app; dialog.print = function(){alert("print in dialog");} function make_dialog(){} make_dialog.prototype = dialog; var button = new make_dialog; button.help = function(){alert("help in button");} button.help(); button.print(); button.preview() すっきり書けてるほうとは思うけど、どうも…
476 名前:デフォルトの名無しさん mailto:sage [04/02/19 10:54] >>475 __proto__ 版 var app = new Object; var dialog = new Object; var button = new Object; app.preview = function(){alert("preview in app");} dialog.print = function(){alert("print in dialog");} button.help = function(){alert("help in button");} dialog.__proto__ = app; button.__proto__ = dialog; button.help(); button.print(); button.preview() やっぱりこっちの方がプロトタイプっぽい。
477 名前:デフォルトの名無しさん mailto:sage [04/02/19 13:18] var app = new Function; app.prototype.preview = function(){alert("preview in app");} var dialog = new Function; dialog.prototype = new app; dialog.prototype.print = function(){alert("print in dialog");} var button = new dialog; button.help = function(){alert("help in button");} クラスっぽく書くとこうか:p
478 名前:デフォルトの名無しさん mailto:sage [04/02/19 15:46] 昔なつかし function app(){ var name = "app"; this.preview = function(){alert("preview in" + name);}; } function dialog(){ var name = "dialog"; app.apply(this, arguments); this.print = function(){alert("print in" + name);}; } var button = new dialog; button.help = function(){alert("help in button");};
479 名前:1 [04/02/23 15:58] soopy版 app = { fun preview() { do: println "preview in app"; }; }; dialog = app + { fun print() { do: println("print in dialog"); }; }; button = dialog + { fun help() { do: println("help in button"); }; }; button help (); button print (); button preview();
480 名前:デフォルトの名無しさん mailto:sage [04/02/25 19:17] なんか色々中途半端とか言われてるけど、 結局はこれ使って何するのか、だと思うよ。 これ使ったら開発効率が上がりました、 実行効率が上がりました、 保守がしやすくなりました、 ってスタンスのパラダイムじゃないよね。>プロトタイプベース 趣味?
481 名前:デフォルトの名無しさん mailto:sage [04/02/25 19:51] >>480 んー Newton Script なんかがまさにそうなんだけど、例えば HTML / XHTML のように UI + action なんかをさらーっと記述するフレームワークなんかを考えると、ごく当たり前に プロトタイプベースの発想になったりします。 <a id="a" onClick="hoge()"> a </a> <a id="b" onClick="bar()"> b </a> なんていうようなものを表現するとき、それぞれにクラスを作るのではなくインスタンス毎に メソッドを定義して済ませてしまうとか。
482 名前:デフォルトの名無しさん mailto:sage [04/02/25 21:55] UI + action というか、 すでにインスタンスベースの枠組み(UI + actionはその典型)があって、 それに乗っかる場合、っていう意味だろうか。 なんか受け身で消極的な感じがする。
483 名前:デフォルトの名無しさん mailto:sage [04/02/26 08:19] マルチスレッドとの相性ってどうなんでしょうか。
484 名前:デフォルトの名無しさん mailto:sage [04/02/26 12:56] >>482 乗っかるというか、全体を構築するために使ってもいいし (Newton は後者)。 ただ、フレームワークそのものはクラスベースでいいんじゃない、っていう見解は ある意味当たり前にあって(フレームワークで定義されるものは普通汎用性を持っていて、 個別インスタンスなんて珍しいから)、そういう面では prototype 言語でも内部的に クラスを使っていたりします。 ↑漏れはNewtonScript と SpiderMonkey (Netscape 由来の JavaScript エンジン)位 しか詳しくないので信頼度低いけど。
485 名前:デフォルトの名無しさん mailto:sage [04/03/04 16:33] ttp://www.ogis-ri.co.jp/otc/hiroba/technical/Classification/C3_1.html C++でテンプレートによる「修飾」継承という手で爆発を抑えつつ多重分類を実現できそうな気が。
486 名前:デフォルトの名無しさん [04/03/13 12:29] あげ
487 名前:デフォルトの名無しさん mailto:sage [04/03/19 17:47] >>480 >>481 保守、ついでに戯言 Delphi の procedure | function 型のプロパティとか、 Java の匿名内部クラスとかでイベントを捕獲するのは、 メソッドをカスタマイズするという点でプロトタイプに通じる考えだと思う。 あると便利、なくてもほかに手段があれば別に困らないかもしれない。
488 名前:デフォルトの名無しさん mailto:sage [04/03/20 01:40] プロトタイプベース言語の proto ってクラスベース言語の super みたいな物であってますか? どちらも、元のオブジェクトへの参照を保持しているだけですよね?
489 名前:デフォルトの名無しさん mailto:sage [04/03/20 03:51] >>488 selfとsuperは同じオブジェクトを指す
490 名前:デフォルトの名無しさん mailto:sage [04/03/20 12:52] >>489 言語によるかも。
491 名前:デフォルトの名無しさん mailto:sage [04/03/20 13:26] >>488 SELF のリファレンスマニュアルのこれ、 research.sun.com/self/release_4.0/Self-4.0/Tutorial/Language/SyntaxAndSemantics/Resends.html なんかみてみてもらうとわかると思うけど、それであながち間違いでもなさそう。 SELF の場合、self は self のままで(まぎらわしいなぁ…)、メソッドの呼び出し記述のほう に resend を冠する。ただ、これはペアレント(aka proto)スロットが一つのときで、複数ある ときはそれを明示的にするためにペアレントスロット名をもって resend に代える、とある。 まあ、SELF の話をされてもかなわんよ…という人も多いだろうから、なんか他の言語でも 調べてみることにするか。
492 名前:デフォルトの名無しさん mailto:sage [04/03/22 19:33] プロトタイプチェインについての覚書(ECMAScript, JavaScript) ttp://members.jcom.home.ne.jp/jintrick/Personal/d20043l.html#d20_1
493 名前:デフォルトの名無しさん mailto:sage [04/03/24 22:39] インスタンスを実体、クラスを概念とすると、「継承」というものを現実世界で例えた場合に プロトタイプベースとクラスベースの、どちらがより簡単で判り易い例えができるんでしょうね クラスベースはクラス,つまり概念の継承なので、クラスに慣れるとクラスの例は 『クーラーボックスの親はただの箱』みたいでも違和感無いですが、 一般人には???な話でしょうし。(ちょっと説明すればわかると思いますが) 逆にプロトタイプの例では特定の個人を例に挙げなければ難しいですし。 (実際にプログラム内で操作するのは「個人」ですから、 実際の例を出せばこちらのほうが俺は判り易いと思いますが) というかインスタンスとクラスの区別が厳密についてないですね俺 orz クラスが無い分プロトタイプのほうが簡単ですか?
494 名前:デフォルトの名無しさん mailto:sage [04/03/24 22:41] > クラスを概念 そこがもーダメなような
495 名前:493 [04/03/24 22:46] そか orz 判ったつもりで判ってなかったんだな
496 名前:デフォルトの名無しさん mailto:sage [04/03/24 22:47] ごめん下げ忘れた。逝ってきます。
497 名前:デフォルトの名無しさん mailto:sage [04/03/25 12:02] >>493 んー。やっぱり プロトタイプベース vs クラスベース という構図が そも間違っていると思う。プロトタイプベースはよりプリミティブな オブジェクトモデルなんで、クラスベースがよい仕事をする問題領域なら 機能を制限してそうしたフレームワークを組めばいい(ひらたく言えば クラスベースを使えばいい) プロトタイプベースが活きるのは、 クラスベースが到達できない領域なのよ。その最たるものがインスタンス に独自のメソッドや属性を持たせるってやつで。
498 名前:デフォルトの名無しさん mailto:sage [04/03/25 12:26] >>497 それは別にクラスベースでもできるでしょう。 例: python, CLOS, 他のにもあるハズ 嬉しいのは「よりプリミティブである」って事だけなの?
499 名前:デフォルトの名無しさん [04/03/25 12:32] 結局Ruby最強ってことで
500 名前:デフォルトの名無しさん mailto:sage [04/03/29 13:10] 乙
501 名前:デフォルトの名無しさん mailto:sage [04/03/29 20:36] 500 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 14:16 まえにも見たな、この展開… (w >>498 とりあえず、任意の instance から別の instance 作れるとか。 class と instance を兼用させるようなことができる。 501 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 14:29 >>500 > とりあえず、任意の instance から別の instance 作れるとか。 > class と instance を兼用させるようなことができる。 で、それも、どっちもclass baseでもできるんだよな。 502 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 17:46 501は 完全に「実現可能」のレイヤーを取り違えているんだよ。 そんなこと言ったら、Cでもマシン語だって可能だ。 その区別が付かない奴にいくら言っても堂々巡り。 503 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 17:54 >>498 だから、クラスベースの典型例やそこにおける反例として、 プロトタイプベースの素養を持つ CLOS だの Python をひきあいに だすなっちゅうの。わざとか?
502 名前:デフォルトの名無しさん mailto:sage [04/03/29 20:41] 504 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 18:00 >>501 >で、それも、どっちもclass baseでもできるんだよな。 class baseだとclass定義したりそのclassの知識がないとできないから、 ただ「できる」っていうのは無意味。 C言語でOOできると言い張るのと同じ。 prototype baseはinstance を見るだけで追加できるという点で 大きく違う。 それが有効かどうかはともかく。 505 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 18:07 >>498 世に”簡潔は力なり”っていうからねw。 オブジェクトが扱える範囲でよりプリミティブであることは いいことなんでないの?ようわからんけど。 506 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 18:18 >>504 > C言語でOOできると言い張る それはprototype basedでclass basedもできると言うのと違わない のかえ?それが許されるなら、class basedでprototype basedもできる ってのも通るような… 507 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 19:16 形から入る人が多そうなスレですね
503 名前:デフォルトの名無しさん mailto:sage [04/03/29 20:48] 508 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 19:28 > オブジェクトが扱える範囲でよりプリミティブであることは > いいことなんでないの?ようわからんけど。 小さい事は良い事!ってなミニマリストにはそうだろうがねぇ.Scheme なんかは オブジェクトシステム自体が好きにすれば?ということでもっとプリミティブな 仕様になってるが,ミニマリストはあーゆうのが イイ!! って方向にいっちゃうのかね? でもさ,たとえば加算だけ用意すりゃ乗算は不要ってわけでもないだろ?プリミティ ブだから良いって言われてもねぇ.なんか利点をガツーンとたのむわ.>>504 の解説 はわかりやすいなー.あとはそれがどのようにクラスベースよりイイのかを聞いてみたい. 509 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 21:43 >>508 でもさ、インスタンス特異的メソッドや属性がクラスベースで実現可能だからって オブジェクトレベルでそれを実現するモデルを採用したオブジェクトシステムが 用なしってわけもないだろ? なんだ自分で答えてるじゃん。それだよ、それ。 510 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 22:22 お、また堂々巡り繰り返してるな。 511 名前: デフォルトの名無しさん :sage 投稿日: 04/03/25 (木) 22:23 >>508 そうさねぇ。 他人の作った生きているオブジェクトを 改良できることかなぁ。 .NETのClient side Validationはその具体例かな。 # ただインスタンスにメソッドを追加して回ってるだけなんだけどね。
504 名前:デフォルトの名無しさん mailto:sage [04/03/30 01:19] 512 名前: デフォルトの名無しさん Mail: sage 投稿日: 04/03/25 23:13 そして、言語の動的側面を勘違いした椰子が現れて… まわるぅ〜まわるぅよ(ry 513 名前: デフォルトの名無しさん Mail: sage 投稿日: 04/03/25 23:46 一見ループに見えるが完全に同じではない.循環を断ち切れる事を願ってるんだYO!! >>509 の意見とか初耳のような気がするぞ.他人の作った生きているオブジェクトを改良できる? それはプロトタイプベースの特徴なのか?しかし浅学故,それがどうプロトタイプベー スと関連するのかわからない.オブジェクトの受け渡しと特異メソッドが必要だがプ ロトタイプベースとは関係ないんじゃ?と思うんだけど違うのかな. 今のところ 1. 「クラス」がないからシンプル 2. 「クラス」がなくても同等の機能(…なの?) くらいしか理解してないんだが.どうもプロトタイプならではってウリが見えないわ け.インスタンスのコピーはクラスベースだと苦労が多いけど,プロトタイプベース にしたら楽になるのかな?コピーの深さの問題はどうしようもない気がするんだけど. 514 名前: デフォルトの名無しさん Mail: sage 投稿日: 04/03/26 00:05 >>513 循環してるのは一部の人の頭の中だけだと思うよ。それを断ち切りたいなら、 何か言語いじってみれ。
505 名前:デフォルトの名無しさん mailto:sage [04/03/30 01:20] 515 名前: デフォルトの名無しさん Mail: sage 投稿日: 04/03/26 00:34 >>513 プロトタイプベースでは、それなりの規模のシステムではたいてい、トレイトと呼ばれる クラスベースのクラスと同じ枠組みを作ってそれを使っています。したがって、クラスが なくても同等…というのは(解釈のしかたにもよりますが)当たりません。 こうした状況はクラスベースの Ruby が特異メソッドを用意しているのと似ていますね。 違いを際だたせるとすれば、Ruby にあるプロトタイプベースの側面は、特異クラスという ちょっとトリッキーな方法で実現されているのに対して、SELF などでのトレイトは、言語 自体には手を加えずに実現されてているというところでしょうか。 余談ですが、SELF には Ruby とまったく同様の目的と機能を持つミックスインすら Ruby よりはるか以前からエンティティとして実装しています。それも、言語仕様には まったく手を加えずに、です(もっとも、トレイトとミックスインの違いは、継承があるか 無いかの違いだけなわけですが…)。 何度か出ていますが、プロトタイプベースのメリットは、通常は言語仕様として出来合で エンドユーザー(つまりプログラマ)が変更不能な部分を開放したかたちで処理系が提供 されている(できる)ことではないでしょうか。511 さんの言う「自分で改良できる」という ニュアンスにはそんなところも含まれているように感じました。 これは、Smalltalk が処理系全体を Smalltalk 自身で記述し、エンドユーザーが自由に 閲覧、変更、拡張ができるようにしているのと似ていなくもないですね。ただ、SELF の 場合は、Smalltalk では変えられない部分も(たとえば、クラスとインスタンスの関係と いったプリミティブな部分も) SELF 自体でトレイトフレームワークとして表現されている ために、エンドユーザーが到達可能…というわけです。 Ruby の例に戻ると、仮に特異メソッドやミックスインの振る舞いに不満を感じても、まつ もとさんを説得するまで仕様の変更は不可能です。しかし、プロトタイプベースなら自分の 好きに変えてしまえばよいのです。もっとも、これをミニマリズム、動的側面のメリットのとり 違い…と言われてしまえばそれまでですが。