Ruby學習之物件模型

來源:互聯網
上載者:User

標籤:

這兩周工作內容較多,平時自己也有點不在狀態,學的東西有點少了,趁著現在還有點狀態,趕緊複習一下之前學習的Ruby吧。

Ruby是我真正開始接觸動態語言魅力的第一個語言,之前雖然也用過且一直用perl、python等指令碼語言,但是只是作為unix shell的擴充(和工作有關),沒有真正地審視動態語言的哲學。是《Ruby元編程》這本書,好像給我開啟了一扇新世界的大門,書中介紹的每一個特性都讓我興奮地幾乎跳起來,這就是學習的魅力吧。

Ruby語言初探

由於是第一個Ruby的隨筆,先簡單介紹一下ruby的文法規則吧。ruby的文法和python有點類似,但是不要求嚴格縮排(當然沒什麼特殊情況縮排是必須的),所以用end關鍵字來表示結束。

說實話還沒有深究過ruby中的每一個變數類型,但是有一點是確定不變的:動態,強型別。所謂的強型別就是一個變數只能只一種類型,不能變成其他類型,而在實際使用中,你會發現一個變數是可以自由隱式轉換的,比如

var=1

var=“string"

不會有任何問題,但是這並不表示ruby就是弱類型語言。和python類似,ruby中的變數其實就是記憶體的引用,當隱式改變一個變數的類型的時候,其實是建立了一塊新的記憶體,並且將變數名指向新的地址,作為新值的引用,而原來的舊的記憶體內容當他的引用次數變成0的時候,就會被系統的記憶體回收機制適時地回收掉。(此處用python的記憶體原理類推了一下,並沒有求證,如果有錯誤,希望大家多多提出)

ruby中用小寫字母或者底線開頭的關鍵字作為變數名,以@開頭作為執行個體變數名,用class關鍵字定義類,module關鍵字定義模組,def關鍵字定義方法,initialize方法來構造一個對象,return關鍵字傳回值,用.調用方法等,沒有任何很奇怪的文法,一切看起來都是那麼自然。

Ruby中的對象

Ruby中到處都是對象,每一個對象都來自於某一個類,同時這個類可能繼承於某一個父類。對象又可以稱為類的執行個體,對象的屬性,也就是類的執行個體變數,存放在對象中,而對象的方法,也就是類的執行個體方法,存放在類中。所以同一個類下的不同執行個體可以共用方法,但是執行個體變數確是不共用的。每一個類都繼承與Object類,Object類中存放諸如class()(查看對象的類)等方法,而Object又是繼承自BasicObject類(白板類,建立繼承自白板類的對象可以消除之前可能存在的所有方法)。每一個對象的類都是Class,Class只是一個封裝了new()等方法的Module......

說起來有點拗口,我大致畫了一下(實線表示class,虛線表示superclass):

Ruby中的方法

當你調用一個對象的方法時,系統會從該對象的類中尋找是否有該方法,如果沒有找到,則會依次到上一級父類中尋找,直到找到該方法,如果沒有找到,則會調用method_missing()方法,調用幽靈方法,或者報出調用錯誤的資訊。可以調用ancestors方法,查看當前對象的祖先鏈(即上述尋找過程的鏈結構,特別的,在Object之後,會尋找Kernel模組,這是由於Object包含了Kernel模組,Kernel中包含print等方法),Ruby就是在祖先鏈上依次尋找方法。

找到方法後,自然要執行了,然而按照以上所說,方法的尋找需要經過一個祖先鏈,那麼在調用這個方法的時候又是如何確定接受者的呢?在Ruby中,每一行代碼都會在當前對象中執行,這個當前對象就是self,沒有明確指定接受者的方法都在self上調用。

事實上,每個Ruby指令碼執行時,都會建立一個main對象作為當前對象,此時,self就是main(main又可以稱作頂級上下文,正如python中的頂格書寫的代碼,而不是c,c++中入口函數的概念)。

Ruby中的私人方法也和c++中有所不同。private關鍵字後面的方法只能被隱含接受者調用,(又由於調用方法時,如果接收者不是自己,則必須明確指定一個接收者,上述底線文字)所以私人方法只能被自身調用。檢查私人方法調用是否合法,只需檢查是否指定了接收者(否)以及當前的self是誰。

擴充:在Ruby中,有種邪惡的方式可以得到任何規則的豁免來訪問任何方法,包括private,即send方法。

Ruby中的類操作

在Ruby中,用class關鍵字定義一個類, 如果這個類不存在,那麼會建立這個類,如果這個類存在了,則會對已有的類添加方法、屬性等。這個操作對內建的類同樣有效。如書上的一個例子,去除字串中非字母、數字、空格的其他符號。想到的是一個用Regex來處理的方法:

def to_alphanumeric(s)

? ? s.gsub /^\w\s/, ‘‘

end

在Ruby中,可以“開啟”String類,並且在類中直接添加該方法:

class String

? ? def to_alphanumeric

? ? ? ? gsub /^\s\w/, ‘‘

? ? end

end

於是在String中多了一個新的方法to_alphanumeric。

ps:這是我第一次知道可以有這樣的定義方式,這讓我感到耳目一新,就像開了一扇窗,外面全都是新的景色。

“開啟”類添加方法的操作看起來很酷,但是仔細思考的話,其實是存在一定問題的:如果在String中,已經存在了to_alphanumeric方法,那麼調用時是不能確定調用到哪個方法的。(截止到寫這篇隨筆的時候,我還不是很清楚在Ruby中實現C++的多態,或者是override等方式是什麼樣子的)

Ruby中的常量和模組

和python類似,用大寫字母開頭來表示一個常量。常量只在當前範圍下有效,類似於分類樹的結構,其他範圍下的同名常量就像是不同目錄下的同名檔案,是不相關的。

從隨筆開始的中,Module是Class的superclass,其實Module(模組)就是一些執行個體方法的集合,和Class就是封裝了若干功能的Module(如new()方法)。Module和Class非常類似,但是使用又截然不同,當需要被繼承或者執行個體化的時候,應該選用Class(superclass()方法和new()方法),而當需要被其他地方包含(include、import)時,應該使用模組。

模組就像是目錄,模組中的不同常量(方法或者屬性的引用)就可以看成是檔案,常量和模組組成一個類似檔案樹的結構,調用時用雙冒號來表示路徑(::)。用加上路徑的顯示方式可以唯一確定到常量的位置,這就是命名空間的概念。

Ruby學習之物件模型

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.