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灯, 水草

请输入看板名称,例如:e-shopping站内搜寻

TOP