佳木斯湛栽影视文化发展公司

主頁 > 知識庫 > Ruby和元編程之萬物皆為對象

Ruby和元編程之萬物皆為對象

熱門標(biāo)簽:硅谷的囚徒呼叫中心 客戶服務(wù) 語音系統(tǒng) Win7旗艦版 企業(yè)做大做強(qiáng) 呼叫中心市場需求 百度AI接口 電話運(yùn)營中心

開篇

空即是色,色即是空。
空空色色,色色空空,在Ruby語言中,萬物皆為對象。

Ruby是一個面向?qū)ο蟮恼Z言(Object Oriented Language),面向?qū)ο蟮母拍畋绕渌Z言要貫徹的堅定很多。

Ruby中不存在Java中原始類型數(shù)據(jù)和對象類型數(shù)據(jù)之分。大部分Ruby中的的東東都是對象。

所以,想要掌握Ruby和Ruby的元編程,對象就是第一門必修功課。本回就著重研究一下Ruby中的對象.

Ruby中的對象

如果你從其他面向?qū)ο蟮恼Z言轉(zhuǎn)來,一提到得到一個對象你可能會想到建立一個類,然后建立這個類的實(shí)例出來產(chǎn)生一個對象。

在Ruby中這完全是可以的,不過這種先建立類才能獲得對象的過程,聽起來更像是面向類的設(shè)計,而不是面向?qū)ο蟮脑O(shè)計。關(guān)于類的一些東西放到下回再說。

在Ruby中,不存在原始類型的概念,1, 0.3, true/false 甚至 nil都是對象。比如,你可以在irb中嘗試下面的代碼:

復(fù)制代碼 代碼如下:

>> 1.methods
=> ["%", "odd?", "inspect", "prec_i", "", "tap", "div", "", "clone", ">>", "public_methods", "__send__", "instance_variable_defined?", "equal?", "freeze", "to_sym", "*", "ord", "lcm", "+", "extend", "next", "power!", "send", "round", "methods", …more methods…> "is_a?", "ceil", "[]"]
>> 1.class
=> Fixnum

你可以在irb中嘗試一下其他數(shù)據(jù)類型,看看他們的方法和類等等信息。

不只是各種數(shù)據(jù)類型,方法在Ruby中也是對象, 比如下列例子:

復(fù)制代碼 代碼如下:

>> one_plus = 1.method(:+)
=> #Method: Fixnum#+>
>> one_plus.class
=> Method
>> one_plus.call(2)
=> 3

有意思的是,方法對象也是有方法的:

復(fù)制代碼 代碼如下:

>> one_plus.arity()
=> 1

對象到底是什么?

到底什么是對象呢?

簡單的說,**對象就是 狀態(tài) + 行為**

狀態(tài) 就是表明當(dāng)前對象所擁有的屬性,每個同類的對象可能有不同的狀態(tài),這些狀態(tài)保存在實(shí)例變量里面(Instance Variable).

對象的實(shí)例變量可以由instance_variable_set/instance_variable_get來設(shè)定/讀?。?br />

復(fù)制代碼 代碼如下:

>> 1.instance_variable_set(:@my_var, "world")
=> "world"
>> 1.instance_variable_get(:@my_var)
=> "world"

行為 行為就是作用在對象上的動作,就是我們常說的方法。Ruby方法的調(diào)用,類似于smalltalk或者Objectiv-C,采用消息模式。調(diào)用方法相當(dāng)于對這個對象發(fā)送了一個消息。所以對方法的調(diào)用也可以這樣:

在Ruby中,狀態(tài),也就是實(shí)例變量是保存在對象里的,而行為或方法則是存在于對象的類或者mixin的module里面。

在靜態(tài)語言中,編譯時就會確定所調(diào)用的方法是否存在,不存在會產(chǎn)生編譯錯誤。

Ruby中,當(dāng)我們在方法調(diào)用的運(yùn)行時,對象會查找他隸屬的類,module,父類等,來找到相對應(yīng)的方法。

Singleton/Meta/Anonymous/Ghost/Shadow Class

1.Singleton Class: 單例類
2.Meta Class:元類
3.Anonymous Class: 匿名類
4.Ghost Class:鬼類
5.Shadow Class: 影子類

上面的這些東東其實(shí)說的都是一個東西,我喜歡叫它 影子類。

Ruby中每一個對象都一個一個影子類,這個影子類存在于對象跟它所屬的類之間:

對象("obj1") -> 影子類 -> 對象所屬的類(String)

當(dāng)一個對象的方法被調(diào)用時,首先查找的是影子類,之后才是它所屬的類。

上面講到實(shí)例變量存在于對象內(nèi),方法存在于對象的類中。
影子類上的方法,就是只有這一個對象擁有的方法。這個方法通常叫做單例方法(Singleton Method)。

這樣的方法只存在于這個對象上,同一個類的其他對象沒有這個方法,因為他們的影子類不同,其他對象的影子類上沒有這個方法。

復(fù)制代碼 代碼如下:

>> a = "obj1"
=> "obj1"
>> def a.hello
>> puts "hello world"
>> end
=> nil
>> a.hello
hello world
=> nil
>> b = "obj2"
=> "obj2"
>> b.hello
NoMethodError: undefined method `hello' for "obj2":String
    from (irb):49
>> a.singleton_methods
=> ["hello"]
>> b.singleton_methods
=> []

Self

Ruby里面一切都是對象,self也是對象,確切地說是當(dāng)前對象的引用。

前文說Ruby的方法調(diào)用是消息模式,比如obj.method, 消息的接受者是.之前的對象,.之后的是方法及參數(shù)。
如果對象和.沒有出現(xiàn)的話,消息會被默認(rèn)送到self對象。除了作為方法的默認(rèn)接受者,self也是實(shí)例變量的解析對象。

self在ruby一開始的時候,被設(shè)定為一個叫做main的對象,再irb里面可以看到:

復(fù)制代碼 代碼如下:

>> m = self
=> main

self可以被認(rèn)為是一個特殊的變量,它的特殊性在于,你不能給他賦值:
復(fù)制代碼 代碼如下:

>> self = "obj"
SyntaxError: compile error
(irb):77: Can't change the value of self
self = "obj"
      ^

有幾個辦法可以改變self的值,.(obj.method的.)是其中一個,除了.還有class/module關(guān)鍵字。
本回主要關(guān)注跟對象相關(guān)的.

當(dāng)我們用obj.method調(diào)用方法時,接下來的時間代碼的執(zhí)行就會到相應(yīng)的方法里,運(yùn)行的上下文切換到那個對象,self自然也變成了那個對象。用def定義單例方法時,道理也是相通的。 下面的例子可以說明這個self切換的情況。

復(fù)制代碼 代碼如下:

>> a = "obj"
=> "obj"
>> def a.hello_self
>> puts "hello #{self}"
>> end
>> m = self
=> main
>> a.hello_self
hello obj

對象的復(fù)制

前文說對象的存在包括兩部分,一是狀態(tài)/實(shí)例變量,另一個是行為,本回專注講了單例方法和影子類。
Ruby中對象的復(fù)制也有兩種模式,一個是只復(fù)制當(dāng)前的狀態(tài)/實(shí)例變量 dup。另外一種是連同影子類和引用的對象一起復(fù)制,從而把單例方法也復(fù)制一份。

復(fù)制代碼 代碼如下:

>> a = "obj"
>> def a.hello_self
>> puts "hello #{self}"
>> end
>> b = a.dup
=> "obj"
>> b.hello_self
NoMethodError: undefined method `hello_self' for "obj":String
    from (irb):90
>> b = a.clone
=> "obj"
>> b.hello_self
hello obj

其實(shí)有本回上述的這些功能,即便是沒有class,Ruby也可以作為一種Prototype(類似JavaScript)的面向?qū)ο笳Z言了。

你可以建立一個對象,生成默認(rèn)的實(shí)例變量,把行為作為單例方法定以在這個對象的影子類上,然后用clone生成千千萬萬個實(shí)例。當(dāng)然這樣比較麻煩,但卻是可行的途徑之一。

其他Object API

對象還有很多其他的功能,比如可以freeze,另外dup跟clone也有一些其他的引用上面的區(qū)別,dup只復(fù)制引用,clone會吧引用的對象也復(fù)制。

這些都可以在Object類(Ruby所有對象的父類)API上找到,可以查看apidock.com的文檔

例如關(guān)于dup

.dup() produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. dup copies the tainted state of obj. See also the discussion under Object#clone. In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance.

本回完

本回講了些對象相關(guān)的東西,有的很基礎(chǔ),有的是Ruby自身的一些特性。

其中Ruby對象模型中最具特色的兩個特性就是影子類/單例方法和self,最好能深入理解這兩個概念。

且聽下回分解

下回注重一些關(guān)于類的故事。

您可能感興趣的文章:
  • Ruby元編程的一些值得注意的地方
  • ruby元編程之創(chuàng)建自己的動態(tài)方法
  • ruby元編程之method_missing的一個使用細(xì)節(jié)
  • Ruby元編程之夢中情人method_missing方法詳解
  • Ruby元編程技術(shù)詳解(Ruby Metaprogramming techniques)
  • Ruby元編程小結(jié)
  • ruby元編程實(shí)際使用實(shí)例
  • Ruby元編程基礎(chǔ)學(xué)習(xí)筆記整理

標(biāo)簽:濟(jì)南 崇左 喀什 山西 長沙 山西 海南 安康

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Ruby和元編程之萬物皆為對象》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    卢湾区| 定陶县| 包头市| 建昌县| 台东市| 楚雄市| 肥城市| 游戏| 筠连县| 甘南县| 凤庆县| 黄浦区| 齐河县| 墨玉县| 峨山| 成安县| 磐安县| 襄城县| 桐柏县| 兴化市| 铜鼓县| 东辽县| 安陆市| 方山县| 喀喇| 永昌县| 阳泉市| 文山县| 濮阳县| 昌江| 万载县| 宁夏| 武威市| 基隆市| 即墨市| 沁水县| 饶平县| 南丹县| 广安市| 清新县| 习水县|