近在ruby-china中閒逛,無意中發現了一位網友提出的問題,這個問題相當有意思,並且促使我寫下了這篇部落格。
原問題是這樣描述的:
class
object
defdo_it
puts
"do it"
endend
object
.do_it
#這個class method 怎麼來的?
object
.new
.do_it
簡單的幾行**,我竟一時答不上來,不禁汗顏!接觸ruby也有一年多了,自認為很熟悉這門語言,但這個問題卻把自己打回原型。不過我相信,至少有90%的ruby程式設計師會被這個問題難住,所以我覺得很有必要研究一下這個問題,讓自己,也讓別人搞明白,為什麼會這樣。
首先,我想每個人心中都會有這樣乙個疑問:
do_it
很明顯是object
物件的例項方法,而object
是乙個類,類怎麼可以直接呼叫其實例方法呢?
我們暫時放下這個問題,去分析一下object
這個類,它到底有什麼特別之處。
讓我們先寫乙個普通類,看它是否和object
類有相似的特性。
irb
(main
):001:0
>
class
test
irb(
main
):002:1
>
defdo_it
irb(
main
):003:2
>
puts
"do it"
irb(
main
):004:2
>
endirb
(main
):005:1
>
end
我們寫了乙個test
類,它也有乙個do_it
方法,我們可以讓test
類來呼叫do_it
,看會發生什麼:
irb
(main
):006:0
>
test
.do_it
nomethoderror
:undefined
method
`do_it' for test:class
正如我們預料的一樣,test
並不能呼叫do_it
這個例項方法,那object
為什麼可以辦到呢?
irb
(main
):007:0
>
test
.ancestors
=>
[test
,object
,kernel
,basicobject
]irb
(main
):010:0
>
test
.superclass
=>
object
ancestors
方法可以檢視當前類的祖先鏈,我們可以清楚的看到:object
類是test
類的超類(正確來說,所有類最終都繼承於object
)。
ruby中,可以使用class
方法檢視物件所屬的類。
irb
(main
):011:0
>a=
test
.new
=>
#irb
(main
):012:0
>a.
class
=>
test
irb(
main
):013:0
>
test
.class
=>
class
從這裡可以看出ruby中乙個非常重要的概念:類自身也是物件。
既然類自身也是物件,那麼我們也可以把object
類當作物件。
irb
(main
):014:0
>
object
.class
=>
class
irb(
main
):013:0
>
test
.class
=>
class
object
.do_it
在這裡,object
是類還是物件呢?
irb
(main
):024:0
>
object
.instance_methods
=>
[:do_it
,:nil?
,:===,:
=~,:!~
,:eql?
,:hash
,:<=>
,:class
,:singleton_class
,:clone
,:dup
,:taint
,:tainted?
,:untaint
,:untrust
,:untrusted?
,:trust
,:freeze
,:frozen?
,:to_s
,:inspect
,:methods
,:singleton_methods
,:protected_methods
,:private_methods
,:public_methods
,:instance_variables
,:instance_variable_get
,:instance_variable_set
,:instance_variable_defined?
,:remove_instance_variable
,:instance_of?
,:kind_of?
,:is_a?
,:tap
,:send
,:public_send
,:respond_to?
,:extend
,:display
,:method
,:public_method
,:singleton_method
,:define_singleton_method
,:object_id
,:to_enum
,:enum_for
,:==
,:equal?,:
!,:!=
,:instance_eval
,:instance_exec
,:__send__
,:__id__
]
instance_methods
方法可以列印出當前類所擁有的所有例項方法,很明顯,do_it
是obje1ct
類的例項方法。
對於object.do_it
,如果把object
當作類來看,很明顯類無法直接呼叫例項方法,但是如果把object
當作物件來看,情況就不一樣了。
根據ruby的方法查詢方式:沿著祖先鏈查詢。
我們試著找出object
是如何找到do_it
的方法的。
irb
(main
):026:0
>
object
.class
=>
class
//object
所屬的類是
class
,class
中沒有定義
do_it
,然後查詢超類
irb(
main
):027:0
>
class
.superclass
=>
module
//module
中也沒有定義
do_it
,繼續查詢超類
irb(
main
):028:
0>
module
.superclass
=>
object
//my
god!
module
的超類竟然是
object
,而object
中確實定義了
do_it
方法
我們終於找到了do_it方法,一切都真相大白!!!而這一切都如ruby物件模型中描述的一模一樣。
簡單的乙個問題,卻折射出學習ruby三個最重要的知識點:
Ruby 中的類和物件
最近在ruby china中閒逛,無意中發現了一位提出的問題,這個問題相當有意思,並且促使我寫下了這篇部落格。原問題是這樣描述的 class object defdo it puts do it endend object do it 這個class method 怎麼來的?object new d...
Ruby 類和物件
ruby是一種物件導向程式設計語言,具有物件導向的特性 封裝 抽象 繼承和多型性。在ruby中,類以關鍵字class開始,後面跟類名 應大寫 以end結束。例如 class customer end1.2 變數 ruby提供四種型別的變數 區域性變數 區域性變數是在方法中定義的變數。區域性變數在方法...
ruby類與物件
ruby中的物件是類生成的,而類本身也是物件。ruby的頂級類是object其餘所有的類都直接或簡介繼承與object。其中class繼承module,module繼承object,而所有的物件其實都是class類的示例,這其中當然包括object,module,以及class類本身。這便產生了一些...