Ruby 中的類和物件

2021-07-15 17:25:29 字數 4701 閱讀 6988

近在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_itobje1ct類的例項方法。

對於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類本身。這便產生了一些...