Ruby 板


LINE

在看 Ruby 的 class 與 instance 之前,先來看所謂 prototype-based language 是怎麼樣的東西, 當然是舉大家最耳熟能詳的例子,ECMAScript(即 Javascript) 所謂 prototype-based 的意思是,沒有 class 的概念,所有的一切都是 instance, 產生東西一律使用 clone 的手法,從 prototype clone 出來 如果有耐心慢慢看英文的話,這篇很詳細 http://en.wikipedia.org/wiki/Prototype-based_programming 在 ECMAScript 裡,要這樣操作 prototype: =begin 例子 // 產生一個 function object, 會輸出「我是 ooo」 function say(){ print('I am ' + this) } // 產生一個 function object, 拿這當 Duck 的 prototype function Duck(){} // 讓 Duck prototype 產生一個成員,也就是讓 say 變成他的 method Duck.prototype.say = say; // 定義 toString 讓 say 使用 Duck.prototype.toString = function(){ return 'Duck' } // 假設現在有一個讓某東西說話的 function function say_hello(who){ who.say() } // 於是我們可以這樣呼叫 say_hello say_hello(new Duck) =end 例子 new Duck 會去尋找 Duck 的 prototype, 然後 clone 一份該 prototype 後傳回 所以 say_hello 的 who 會是一份 Duck 的複製,執行 say 則會輸出 I am Duck ok, 回到 Ruby. 雖然說 Ruby 被分類成 class-based, 但事實上, everything(ok, almost) is an object in Ruby, 就算是 class, 他其實本質上也是某個 instance, 是 Class 的 instance. class A; end a = A.new a 是 A 的 instance, 所以 a 的 class 是 A. a.class # A A 是 Class 的 instance, 所以 A 的 class 是 Class A.class # Class 其實,我覺得可以把這個 Class 視為某種 meta-class, 即 class 的 class, 如果我們要把 A 當嚴格 class 的話。但如果我們依然把 class 當 instance 看的話,當然,Class 本身其實也是一個 instance, 他是他自己的 instance. Class.class # Class 有趣的是,這樣寫的話: Class.object_id == Class.class.object_id 答案是:true. Class.class 傳回來的,其實就是 Class, 也就是,他是他自己的 instance. 換句話說,其實 Class 是所有的 class 的 class, A.kind_of? Class # true Class.kind_of? Class # true A.class # Class Class.class # Class A.class.object_id == Class.object_id # true (btw, 其實更妙的是: Module.kind_of? Class # true # Module 是 Class 的 instance Class.kind_of? Module # true # Module 是 Class 的 superclass Module.new.kind_of? Class # false # Module 的 instance 不是 Class 再加上 Object 會更複雜,可以試著畫畫看物件結構) 但是回想一下,一般我們是怎麼定義 class 的? class A; end 其實,我個人會說這是一種 syntax sugar, 因為更合於 Ruby object system 的 定義方式,應該是這樣: A = Class.new A.send(:define_method, :say_hello, lambda{ puts "Hello from A's instance." }) a = A.new a.say_hello # Hello from A. 由於 define_method 是 private 的,所以要用 send 去呼叫 其第一參數是你所要回應的 message symbol, 第二參數是 Proc/Method/Block 都可 將會成為該 method 的 body. 也就是說,其實你寫 class A def say_hello puts "Hello from A's instance." end end 對於 A 來說,他是先從 Class 產生一個實體(instance) 然後將 A 這個「常數」指向那個實體,再對 A 呼叫 define_method 把 say_hello 變成 symbol, 將 Block 變成該 method 的 body. 哪一個比較容易寫?當然是後者,畢竟那是大家都很習慣的模式,簡潔易懂 所以我會說那種寫法其實在某種程度上來說,是 syntax sugar... 而 Ruby 其實也是用 prototype 建出其 class 體系, 這樣應該算是 prototype-based 還是 class-based, 看倌認為哩? OK! 回到最早發表這篇文章的動機之來源問題,怎麼刪掉某個 class? 由於以 GC 為記憶體核心模型的程式語言,通常不允許你對某個物件明白刪除 我們能做的只有把他設為 nil, 像是 a = A.new a = nil # 希望 GC 收回 A 當然也是某個 instance, 只是記得「大寫」開頭的 identifier 是常數吧? A 正是一個 const pointer 指向某個 instance(A 的 prototype) A = nil # 希望 GC 收回 這樣就可以很暴力地期望 GC 會回收 A... 我不知道這樣做能不能 work, 只知道肯定會噴 warning, 因為你竄改常數 安全性設高一點的話,這樣做甚至會失敗(因為不能修改常數) 很好!再回想一下,你不能寫 class a; end 因為 class 要大寫開頭(才是常數) 但是你可以這樣寫: a = Class.new a.send(:define_method, :say_hello, lambda{...}) a.new.say_hello # ok a = nil # ok 現在 a 不是常數了,但是他仍然是某個 class! 確實是可以正確地將他指為 nil 了… 可是話說回來,既然都在用 Ruby 了,刪除東西真的是很重要的一件事嗎? 當然不是!記住 scripting 的優勢在哪裡,如果放棄這個優勢,不如去用 system langauge, 如 C++ 之類的會遠比在這邊磨 Ruby 要來得好 最後最後講個題外話,跟本主題沒有關係。 說過很多次個人相當崇拜物件導向,也喜歡各種高度抽象、動態的特性。 而我 Ruby 特性看得越多,某種失落感就越大。 因為以我現在的能力,實在想不太到還有哪些是 Ruby 相當值得改進的部份。 也就是說,Ruby 讓我感覺不到有必要自己下去寫一個全新的語言,他已經夠好了。 剛開始碰 Ruby 時,勾起我很多的想法。可是越碰越多後,發現其實這些在 Ruby 裡面本來就已經有了,而且夠好用了。剩下的交由 lib 實作就可以了, 沒什麼語言可以置喙的地方…。 我想當然,一定還有很多可以改進的,只是以我現在的能力確實看不太出來。 之前貼過一篇文章,Ruby sucks (All those shaky laguages... ) http://www.lrde.epita.fr/~didier/comp/ruby.php 我一直很喜歡這篇,因為其實這篇對 Ruby 有很高的讚譽。 只是完全比不上 Lisp 而已,哈哈。而目前我還不太能夠理解 Lisp... 真的要說的話,目前我還是支持多重繼承,想不太到多重繼承有什麼大問題。 除了讓 compiler 變得很難寫、object system 變得錯綜複雜外,不覺得有什麼問題。 而每一個鋒銳的武器,當然都很有可能會傷到自己人,這是功力問題。 水能載舟亦能覆舟,但這不代表我們要把水給拋棄…。 The Truth about Multiple Inheritance http://www.eiffel.com/general/monthly_column/2006/October.html 這篇也是在讚揚多重繼承。雖然我不是很懂他對 C++ 有什麼不滿。 在 Common Lisp 的 CLOS 中,多重繼承的威力更是非常非常地驚人。 當然我是不太清楚多有威力,畢竟 Lisp 還是離我有點遠,只是, Ruby 如果加上多重繼承的話,也許是一個改進的方向吧。 2007.02.08 -- Nobody can take anything away from him. Nor can anyone give anything to him. What came from the sea, has returned to the sea. Chrono Cross --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.28.18
1F:推 poga:大王m 02/08 18:34
2F:推 skyboy:推 :) 關於class那部份的觀念其實是一樣 02/08 20:15
3F:→ skyboy:不過把名詞的定義還是弄的清楚點 謝了 :D 02/08 20:16
4F:→ godfat:從善如流 XD 不客氣,有問題歡迎再提出 02/08 20:40







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Soft_Job站內搜尋

TOP