Ruby 面向?qū)ο笤?/h1>

ruby面向?qū)ο蟪醪嚼斫?/h3>

類與對(duì)象無疑是ruby的核心楚堤,可能最開始看上去有一點(diǎn)困惑疫蔓,似乎有太多的概念:類、對(duì)象身冬、類對(duì)象衅胀、模塊、實(shí)例方法酥筝、類方法滚躯、單例類.... 太多太多,許多從事ruby開發(fā)的工程師們嘿歌,大多都有其他編程語(yǔ)言的開發(fā)經(jīng)驗(yàn)掸掏,也會(huì)借助其他語(yǔ)言(比如java)的面向?qū)ο罄砟顏砝斫鈘uby,大多數(shù)情況下宙帝,能認(rèn)識(shí)到的也只是千篇一律的 class丧凤、new、initialize等等步脓,很經(jīng)典的Ruby元編程一書中愿待,也有不少朋友覺得面向?qū)ο筮@部分的概念比較繞腦,我決定記錄并分析一下

ruby虛擬機(jī)啟動(dòng)之初靴患,提供了哪些類, 模塊或者說對(duì)象

# 我們隨意創(chuàng)建一個(gè)類
class Aoo
  def hello
    puts 'hello world'
  end
end
# 打印祖先鏈
puts Aoo.ancestors
>> [Aoo, Object, Kernel, BasicObject]
# 打印Aoo單件的祖先鏈
puts Aoo.singleton_class.ancestors
>> [#<Class:Aoo>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
# 打印祖先鏈中各個(gè)對(duì)象的類型
puts Class.class
>> Class
puts Module.class
>> Class
puts Object.class
>> Class
puts Kernel.class
>> Module
puts BasicObject.class
>> Class
puts Aoo.class
>> Class

結(jié)論:

  • Class, Module, Object, Kernel, BasicObject 這幾個(gè)對(duì)象早已被ruby虛擬機(jī)提供仍侥,并且ruby中所有對(duì)象都直接或者間接繼承了他們,眾所周知蚁廓,模塊是需要通過include引入的访圃,并非顯示繼承,不過從模塊被插入祖先鏈來看相嵌,也是一種變相的繼承腿时,并且模塊的此種特性,可以滿足多繼承需要

疑問:

  • 為何Module.class得到的結(jié)果是Class饭宾,而Kernel.class得到的結(jié)果是Module
  • Aoo的祖先鏈和Aoo單件的祖先鏈為何差距這么大
  • 我們所謂的類批糟,比如Aoo, Object, BasicObject,或者我們所謂的模塊看铆,比如Module, Kernel徽鼎,它們的類型要么是Class,要么是Moudle弹惦,是不是意味著這些類都是對(duì)象否淤?
  • 祖先鏈中,Class和Module居然在Object的下方棠隐,是不是意味著它們繼承了Object?

探究原生類或者對(duì)象的繼承關(guān)系

在面向?qū)ο蟮睦碚撝惺眨诵募匆磺薪詫?duì)象,ruby對(duì)此作出了很好的詮釋助泽,在ruby中啰扛,不管是+ - * / 還是一個(gè)我們所說的類,都是一個(gè)對(duì)象


雖然從祖先鏈來看嗡贺,頂層是BasicObject隐解,但實(shí)際上Class、Module才是ruby最初始的核心


我們剛才用.class方法獲取對(duì)象的類型诫睬,在ruby中煞茫,只有類型是Class的才可以被繼承,模塊只能混入摄凡,不可以繼承续徽,ruby里模塊的.class都為Module,但是Module本身是一個(gè)Class架谎,這是ruby自身的設(shè)定


我們把類型為Class的對(duì)象炸宵,叫做類對(duì)象,也就是.class是Class的對(duì)象谷扣,更多時(shí)候土全,我們直接稱作類,由于Class的類型也是Class会涎,所以Class是一個(gè)可以創(chuàng)建類對(duì)象的類對(duì)象

我們查看Class中的自有方法

# 查詢方法時(shí)帶上false參數(shù) 表示只查詢自有方法裹匙,而不查詢繼承得來的方法
puts Class.methods false
>> [] # 結(jié)論 -- Class類并沒有定義自己的類方法
puts Class.instance_methods false
>> [:allocate, :new, :superclass] # 結(jié)論 -- Class僅有3個(gè)公有實(shí)例方法,其中有創(chuàng)建對(duì)象必備的new方法
puts Class.private_methods false
>> [:inherited, :initialize]
puts Class.private_instance_methods false
>> [:inherited, :initialize]
# 結(jié)論 -- Class的私有方法中末秃,類方法和實(shí)例方法相同概页,是用于對(duì)象初始化的initialize

結(jié)論:

  • Class中定義的方法很少,但是包含了面向?qū)ο蟮奶匦?/li>
  • 我們知道练慕,Object/BasicObject的類方法中惰匙,已具備new方法(不知道的朋友可以自己打印出來看
  • new方法定義在Class中技掏,只能從Class獲取,恰好Class中的new方法是實(shí)例方法(類的實(shí)例方法會(huì)作為對(duì)象的類方法)
  • 并且BasicObject/Object的class屬性指明了類型是Class
  • 證明Object/BasicObject..等等帶有new方法的類都是Class的對(duì)象项鬼,所以類也是對(duì)象的一種
  • 注意:Class的私有方法中哑梳,不論類方法還是實(shí)例方法都帶有構(gòu)造方法initialize,證明Class本身也是有實(shí)例化過程的(由虛擬機(jī)實(shí)例化)绘盟,Class本身也是一個(gè)對(duì)象鸠真,正因?yàn)槿绱耍珻lass可以調(diào)用實(shí)例方法的new去創(chuàng)建Object
  • Class非常特殊龄毡,它的類型就是自身吠卷,即Class.class === Class,這是ruby自身設(shè)定沦零,用于形成類型引用的閉環(huán)(下面討論)

以上根據(jù)Class的內(nèi)部方法定義祭隔,以及所有類都具有new方法,證明了所有類都是Class的對(duì)象蠢终,并且Class本身也是對(duì)象

我們?cè)倏纯碝odule

puts Module.methods false
>> [:nesting, :constants]
puts Module.instance_methods false
>> [:freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :singleton_class?, :include, :prepend, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method]
puts Module.private_methods false
>> [:inherited, :initialize]
puts Module.private_instance_methods false
>> [:included, :extended, :prepended, :method_added, :method_removed, :method_undefined, :initialize_copy, :attr, :attr_reader, :attr_writer, :attr_accessor, :initialize, :initialize_clone, :remove_const, :append_features, :extend_object, :prepend_features, :refine, :using, :remove_method, :undef_method, :alias_method, :public, :protected, :private, :module_function, :define_method]

結(jié)論:

  • Module中序攘,私有類方法帶有構(gòu)造方法initialize,證明Module本身也是有實(shí)例化過程的(由虛擬機(jī)實(shí)例化)寻拂,Module本身也是一個(gè)對(duì)象
  • Module中定義了大量在面向?qū)ο笾谐S貌僮鞒痰欤梢钥醋鍪敲嫦驅(qū)ο蟮闹饕獙?shí)現(xiàn)
  • 我們知道,Class雖然自己只有幾個(gè)方法祭钉,但是繼承而來的方法卻很多瞄沙,如果你打印出來看的話,和Module中提供的方法基本一致慌核,所以:Class繼承了Module

以上總結(jié)距境,Class和Module都是由虛擬機(jī)實(shí)例化的對(duì)象,既是對(duì)象也是類垮卓,他們是虛擬機(jī)初始階段提供的核心

在虛擬機(jī)已提供Class和Module的前提下垫桂,就可以開始正常的對(duì)象創(chuàng)建和繼承了,ruby以此為基礎(chǔ)粟按,又創(chuàng)建了Kernel模塊诬滩,BasicObject, Object

  • Kernel -- 定義了大量常用工具方法比如輸入輸出之類的,通過Module.new創(chuàng)建
  • BasicObject -- 基本是個(gè)空的類灭将,可以作為潔凈室疼鸟,通過Class.new創(chuàng)建
  • Object -- 該類作為我們自定義類的基類,暴露給我們使用庙曙, 通過Class.new創(chuàng)建

疑問:

  • Module哪來new方法空镜,雖然它和Class一樣,有虛擬機(jī)幫助實(shí)例化,既是類也是對(duì)象吴攒,但是Module不管類方法還是實(shí)例方法都沒有new张抄,它得從Class中繼承到new方法才行,然而剛才已經(jīng)證明Class繼承了Module

Ruby核心對(duì)象的繼承方式舶斧,其實(shí)是一個(gè)環(huán)

簡(jiǎn)單示例

Module要想獲取new欣鳖,沒法繼承Class察皇,因?yàn)镃lass已經(jīng)繼承了Module茴厉,由于他們的.class都是Class,所以可以繼承Class的實(shí)例化對(duì)象Object(也可以叫做類對(duì)象)什荣,所以Class Module Object構(gòu)成了環(huán)狀繼承關(guān)系矾缓,Module和Class中的實(shí)例方法,在Object中以類方法的形式存在(因?yàn)镺bject是Class對(duì)象)稻爬,當(dāng)Module繼承Object之后嗜闻,獲取了Object的類方法,換而言之桅锄,此種方式琉雳,讓自己的實(shí)例方法轉(zhuǎn)變?yōu)榱祟惙椒ǎ@3個(gè)對(duì)象間形成了方法的大范圍共享友瘤,以此為基礎(chǔ)翠肘,才有了ruby各種面向?qū)ο髾C(jī)制

ruby的單件

我們回到之前提到的單件類的祖先鏈問題,對(duì)比下兩種情況下的祖先鏈

# 打印Aoo單件的祖先鏈
puts Aoo.singleton_class.ancestors
>> [#<Class:Aoo>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
# 為何Aoo的單件祖先鏈不是如下 辫秧?束倍??盟戏?绪妹?
[#<Class:#Aoo>, Class, Module, Object, Kernel, BasicObject] 
# 打印Aoo實(shí)例化對(duì)象的祖先鏈
puts Aoo.new.singleton_class.ancestors
>> [#<Class:#<Aoo:0x007fdac100dba8>>, Aoo, Object, Kernel, BasicObject] 
# 如果我們定義一個(gè)類去繼承Aoo
class Boo < Aoo
end
puts Boo.new.singleton_class.ancestors
>> [#<Class:#<Boo:0x007fdabf8d48d8>>, Boo, Aoo, Object, Kernel, BasicObject]

總結(jié):

  • 如果你平時(shí)仔細(xì)觀察,會(huì)發(fā)現(xiàn)柿究,Class的直接對(duì)象(類對(duì)象)和普通類的對(duì)象邮旷,他們單間類的祖先鏈會(huì)出現(xiàn)這兩種情況
  • 我們知道,ruby的單件是無限的蝇摸,除了單件婶肩,還有單件的單件 ......,可以無限遞歸下去探入,所以單件類在被我們使用前狡孔,是不會(huì)自己實(shí)例化的,只有當(dāng)我們?cè)L問單件的時(shí)候蜂嗽,才會(huì)實(shí)例化單件苗膝,并且這個(gè)單件也是當(dāng)前對(duì)象.class所指明類型的實(shí)例

當(dāng)你訪問對(duì)象單件的時(shí)候,絕對(duì)不僅僅只是根據(jù)類型再創(chuàng)建一個(gè)實(shí)例植旧,比如我們?cè)L問Aoo的單件辱揭,不僅生成了Class:Aoo离唐,還有Class:Object,Class:BasicObject

  • 主要區(qū)別還是在于對(duì)象的.class是否是Class问窃,也就是看它是否是一個(gè)類對(duì)象亥鬓,如果當(dāng)前對(duì)象是一個(gè)類對(duì)象,證明它的單件也一定是一個(gè)Class的實(shí)例域庇,既然都是類對(duì)象嵌戈,就會(huì)有相同的繼承關(guān)系,所以Aoo單件的祖先鏈听皿,會(huì)先列出[#<Class:Aoo>, #<Class:Object>, #<Class:BasicObject>]
  • 普通對(duì)象的的.class并非Class熟呛,對(duì)象自身并沒有所謂的繼承關(guān)系,所以普通對(duì)象的單件不涉及祖先鏈尉姨,直接就追溯到了類對(duì)象本身

最后

  • Class和Module是由虛擬機(jī)提供的特殊類庵朝,之后的一切類都由Class創(chuàng)建
  • 被new創(chuàng)建出來的,可以是對(duì)象又厉,也可以是類對(duì)象(類)九府,對(duì)象的.class屬性為Class的都是類對(duì)象,Class不僅可以創(chuàng)建類對(duì)象覆致,自身也是一個(gè)類對(duì)象
  • Class中定義了創(chuàng)建對(duì)象的基本方法侄旬,比如new
  • Module中定義了大量類操作相關(guān)方法
  • Class、Module篷朵、Object勾怒、Kernel、BasicObjec這一層的初始化操作對(duì)用戶透明声旺,將Object作為自定義類的基類
  • 類對(duì)象(類)的實(shí)例方法會(huì)作為對(duì)象的類方法
  • Class笔链、Module、Object的繼承關(guān)系腮猖,讓他們的類方法與實(shí)例方法相同鉴扫,BasicObject只是沒有混入Kernel,作為一個(gè)類對(duì)象澈缺,Class和Module中的方法是必不可少的坪创,并不是所謂的內(nèi)部幾乎沒有方法
  • 單件是訪問的時(shí)候產(chǎn)生,并且根據(jù)繼承關(guān)系不同姐赡,產(chǎn)生的單件個(gè)數(shù)不同莱预,會(huì)為單件生成一個(gè)完備的祖先鏈

ruby的元編程和面向?qū)ο蟮乃季S確實(shí)很繞,自己琢磨的過程中也只是略有收獲而已项滑!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末依沮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌危喉,老刑警劉巖宋渔,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異辜限,居然都是意外死亡皇拣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門薄嫡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氧急,“玉大人,你說我怎么就攤上這事岂座√伲” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵费什,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我手素,道長(zhǎng)鸳址,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任泉懦,我火速辦了婚禮稿黍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘崩哩。我一直安慰自己巡球,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布邓嘹。 她就那樣靜靜地躺著酣栈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汹押。 梳的紋絲不亂的頭發(fā)上矿筝,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音棚贾,去河邊找鬼窖维。 笑死,一個(gè)胖子當(dāng)著我的面吹牛妙痹,可吹牛的內(nèi)容都是我干的铸史。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼怯伊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼琳轿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤利赋,失蹤者是張志新(化名)和其女友劉穎水评,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體媚送,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡中燥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了塘偎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疗涉。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吟秩,靈堂內(nèi)的尸體忽然破棺而出咱扣,到底是詐尸還是另有隱情,我是刑警寧澤涵防,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布闹伪,位于F島的核電站,受9級(jí)特大地震影響壮池,放射性物質(zhì)發(fā)生泄漏偏瓤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一椰憋、第九天 我趴在偏房一處隱蔽的房頂上張望厅克。 院中可真熱鬧,春花似錦橙依、人聲如沸证舟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)女责。三九已至,卻和暖如春慧域,著一層夾襖步出監(jiān)牢的瞬間鲤竹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工昔榴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辛藻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓互订,卻偏偏與公主長(zhǎng)得像吱肌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仰禽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理氮墨,服務(wù)發(fā)現(xiàn)纺蛆,斷路器,智...
    卡卡羅2017閱讀 134,661評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法规揪,類相關(guān)的語(yǔ)法桥氏,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法猛铅,異常的語(yǔ)法字支,線程的語(yǔ)...
    子非魚_t_閱讀 31,639評(píng)論 18 399
  • 最近復(fù)習(xí)了下 ruby 對(duì)象模型的知識(shí),參照了 Ruby Metaprogramming奸忽,于是邊看邊做筆記堕伪,還是收...
    張羽辰閱讀 530評(píng)論 0 4
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,720評(píng)論 0 9
  • 下周Guns n' Roses就要來維也納巡演了栗菜! 于是這兩天上下班路上開始重溫他們所有的專輯欠雌,今天聽到這首耳聞能...
    天休問閱讀 549評(píng)論 0 1