- 浏览: 217408 次
文章分类
- 全部博客 (155)
- activerdf (1)
- html (0)
- depoly (1)
- src_present (1)
- ria (1)
- beast (2)
- cache (1)
- acts_as_atggable (1)
- http (1)
- talk (1)
- rest (1)
- rake (1)
- vim (2)
- active_resource (1)
- jruby activerecord_jdbc (1)
- nginx (1)
- plugin (1)
- gui (1)
- push (1)
- 介紹 (1)
- rails (19)
- regex (1)
- svn (1)
- 說明 (13)
- gem (4)
- ruby (16)
- rails12 (2)
- fastcgi (1)
- os (1)
- mongrel (5)
- scale (4)
- quickref (1)
- 安裝 (5)
- tiobe_index (2)
- planet (1)
- lighttpd (4)
- Capistrano (1)
- 嘴砲 (2)
- performance (4)
- ide (6)
- jruby (12)
- railsconf (1)
- activerecord (2)
- ajax (3)
- ruby.net (1)
- 程式 (1)
- actionmailer (1)
- company (2)
- security (1)
- redmine (1)
- book (2)
- news (2)
- 廣告 (1)
最新评论
-
bluerose:
你好,我下载了文件是Textile格式的。应该怎么阅读呢?我想 ...
Textile,RedCloth,Vim -
whg333:
谢谢,LZ是香港或台湾人士?怎么都是繁体?
學習 Ruby on Rails 要看的書 -
jerry:
https可以作吗?
Net::HTTP 使用方式 -
thinhair:
能不能具体点? 这个Config文件在那啊?
用 JRuby 來連接 Oracle -
dearsuper:
就是希望少占资源。
Another Ruby IDE:InterlliJ Idea for Ruby Plugin launch
不知道為何,最近不管是私事或公事似乎都很多。造成的結果就是很多事不知道該從何處著手比較好。也許短時間內沒辦法寫什麼新東西也說不定,所以我又拿舊文章出來改了。這次講的是 Ruby 的物件系統。不過呢,由於這篇原本是回答別人的問題,因此有些地方講得不是很齊全,有些也講得比較偏。找到時間後,會再重新整理一次,現在就先這樣吧
編輯筆記:後面一段無關的刪去了,並補充了一小段。
==
在看 Ruby 的 class 與 instance 之前,先來看所謂 prototype-based language 是怎麼樣的東西,當然是舉大家最耳熟能詳的例子,ECMAScript(即 Javascript)
所謂 prototype-based 的意思是,沒有 class 的概念,所有的一切都是 instance, 產生東西一律使用 clone 的手法,從 prototype clone 出來。
在 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's instance.
由於 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, 看倌認為哩?
2007.02.08
補充:
有在寫 Ruby 的人,應該都知道 class 的名稱一定要大寫開頭。事實上,這只是一種延伸規則,並不是基本的規則。依照:
a = Class.new
仍然是可以得到一個不是大寫開頭的 class. 大寫開頭的 identifier 在 Ruby 是一個更簡單的概念:「常數」(constant)。也就是說,其實每一個 class name 都是一個常數,一個 constant variable refer to a Class's instance, 一個指向 Class 實體的常數,就跟一般的變數沒兩樣。所以我們可以寫:
def make klass
klass.new
end
這個 functiona 接受一個參數,這個參數的 type 的必要條件是實作 new method, 而任何一個 Class instance 都符合這個條件。
make(Array).push(123)
把 Array 這個 instance 丟給 make 這個 function, 回傳就是一個 Array instance.(global function 也值得探討,不過還是留待下次吧 :p)
那麼為什麼要讓 Class instance 成為一個常數?其實這是很顯而易見的,如果你把原本定義好的 class 整個變成其他人了,例如:
Array = String
這樣意義在哪裡?以後寫 Array.new 產生的就不是原本的 array, 而是 string 了。所以讓 class 成為一個 constant, 並要求其開頭字母是大寫,並非單純只是為了命名習慣的問題,背後是還有牽扯到其他因素的。
我覺得 Ruby 有趣且厲害並迷人的地方就在於,他不單單只是有強大的威力在內,還額外提供了許許多多方便使用的 syntax sugar, 使任何人都能快速上手,也能快速做到任何他想做到的事情。而當你需要更強大的表達能力時,也能立刻拋棄 syntax sugar, 從最原始的 Ruby 道理開始寫起程式。也就是說,Ruby 提供了各種不同的寫程式角度,大家都可以去找他喜愛的角度去使用。個人認為,Lisp 會不及 Ruby 方便,最主要的差別就在這裡了。(當然,我並不熟 Lisp, 所以這句話恐怕是大有問題在…。)
2007.03.27 godfat 真常
延伸閱讀
編輯筆記:後面一段無關的刪去了,並補充了一小段。
==
在看 Ruby 的 class 與 instance 之前,先來看所謂 prototype-based language 是怎麼樣的東西,當然是舉大家最耳熟能詳的例子,ECMAScript(即 Javascript)
所謂 prototype-based 的意思是,沒有 class 的概念,所有的一切都是 instance, 產生東西一律使用 clone 的手法,從 prototype clone 出來。
在 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's instance.
由於 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, 看倌認為哩?
2007.02.08
補充:
有在寫 Ruby 的人,應該都知道 class 的名稱一定要大寫開頭。事實上,這只是一種延伸規則,並不是基本的規則。依照:
a = Class.new
仍然是可以得到一個不是大寫開頭的 class. 大寫開頭的 identifier 在 Ruby 是一個更簡單的概念:「常數」(constant)。也就是說,其實每一個 class name 都是一個常數,一個 constant variable refer to a Class's instance, 一個指向 Class 實體的常數,就跟一般的變數沒兩樣。所以我們可以寫:
def make klass
klass.new
end
這個 functiona 接受一個參數,這個參數的 type 的必要條件是實作 new method, 而任何一個 Class instance 都符合這個條件。
make(Array).push(123)
把 Array 這個 instance 丟給 make 這個 function, 回傳就是一個 Array instance.(global function 也值得探討,不過還是留待下次吧 :p)
那麼為什麼要讓 Class instance 成為一個常數?其實這是很顯而易見的,如果你把原本定義好的 class 整個變成其他人了,例如:
Array = String
這樣意義在哪裡?以後寫 Array.new 產生的就不是原本的 array, 而是 string 了。所以讓 class 成為一個 constant, 並要求其開頭字母是大寫,並非單純只是為了命名習慣的問題,背後是還有牽扯到其他因素的。
我覺得 Ruby 有趣且厲害並迷人的地方就在於,他不單單只是有強大的威力在內,還額外提供了許許多多方便使用的 syntax sugar, 使任何人都能快速上手,也能快速做到任何他想做到的事情。而當你需要更強大的表達能力時,也能立刻拋棄 syntax sugar, 從最原始的 Ruby 道理開始寫起程式。也就是說,Ruby 提供了各種不同的寫程式角度,大家都可以去找他喜愛的角度去使用。個人認為,Lisp 會不及 Ruby 方便,最主要的差別就在這裡了。(當然,我並不熟 Lisp, 所以這句話恐怕是大有問題在…。)
2007.03.27 godfat 真常
延伸閱讀
发表评论
-
ludy 0.0.4 released
2007-08-12 17:00 1134花了一點時間再測試了一下 curry 的實做,i am gla ... -
ludy 0.0.3 released
2007-08-07 06:09 1240睽違已久,忽然心血來 ... -
[心得] RubyCocoa
2007-07-25 14:37 1442轉自 ptt MacDev 板作者 godfat (godfa ... -
ruby facets
2007-07-08 14:22 1108老實講,ruby 有一個地方真討厭,那就是每次都把我想做的東西 ... -
心愛的 Object 變心啦
2007-05-15 15:36 863剛剛發現一個很有趣的事情,寫 code 的時候,有兩個 Mod ... -
[Ruby] recursive lambda
2007-04-16 15:36 1057[Ruby] recursive lambda==本文 ... -
Struct:簡單的宣告物件方式
2007-04-04 03:08 1252在 PHP 裡面,很多時候我們會用到 Hash 來傳遞變數,像 ... -
Gentoo 上面跑 DRB 可能出現的問題
2007-03-21 13:35 1145有時候在 Gentoo 上面使用一些有關 DRB 的東西,像是 ... -
SWIG/Ruby
2007-03-18 07:36 1756以下文章最早發表於 200 ... -
why scripting?
2007-03-16 15:00 1069why scripting?簡單一句話就是:「為了增進生產力」 ... -
為啥我得升級 Ruby 1.8.6
2007-03-16 16:11 1172為什麼我得升級 Ruby 1.8.6?會跟 Rails 衝突, ... -
Ruby 1.8.6 Release:要升級請三思
2007-03-13 14:29 1063今天早上宣布的,想看詳細情形,或是下載 Source 請看這裡 ... -
M$ 也加入 Ruby 這個大戰場了嗎?
2007-02-25 09:04 1165InfoWorld 上面有消息指出,M$ 對 Ruby 這個程 ... -
Ruby on PSP?
2007-02-03 04:06 1159DSCN0841Originally uploaded ... -
[轉錄] 世界喜愛 Ruby 的理由 - 專訪松本行弘(摘要)
2007-01-06 03:26 1315這是日経 BP主辦的「次世代開發論壇」時的訪談 Matz (R ...
相关推荐
this a java instance about innerclass application
An MFC class to implement single instance apps(17KB)
Class-Weighted Convolutional Features for Visual Instance Search.pdf
Single Instance of an Application Class (21KB)
VB版RichEdit封装类含实例VB version of RichEdit wrapper class with an instance of
今天小编就为大家分享一篇对Python中class和instance以及self的用法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
Instance inner 实例内部类 马克-to-win java视频的介绍
NULL 博文链接:https://wuaner.iteye.com/blog/1009134
A Single-Instance Application Class(54KB)
C#多态性实例,向基类构造函数传递参数C # Polymorphism instance, the base class constructor to pass parameters
C++ convenience class to communicate with a Matlab instance.
Java中 Class.forName()_newInstance()_New_三者区别。
instance_eval方法 这个BasicObject#instance_eval有点类似JS中的bind方法,不同的时,bind是将this传入...class MyClass def initialize @v = 1 end end obj = MyClass.new obj.instance_eval do self #=> #<M
exploit class-specific shape priors by learning a low dimensional shape-space from collections of CAD models. We present novel representations of shape and pose, that strive towards better 3D ...
Instance inner 实例内部类 马克-to-win java视频的介绍
Instance inner 实例内部类 马克-to-win java视频的介绍
Instance inner 实例内部类 马克-to-win java视频的介绍
These include methods to read the tape5 file format into a Mod5 class “instance” or “object”, alter the case instance described in the file, write the tape5 format back to a file, run MODTRAN on ...