Ruby元編程

  • 方法
  • 代碼塊
  • 類宏
  • Eval方法

實例變量、方法、類

實例變量(Instance Variables)是當你使用它們時,才會被建立的對象。因此,即使是同一個類的實例,也可以有不同的實例變量。

從技術層面上來看,一個對象(實例)只是存儲了它的實例變量和其所屬類的引用。因此,一個對象的實例變量僅存在于對象中,方法(我們稱之為實例方法(Instance Methods))則存在于對象所屬的類中。這也就是為什么同一個類的實例都共享類中的方法,卻不能共享實例變量的原因了。

  • 類也是對象。
  • 因為類也是一個對象,能應用于對象的皆可運用于類。類和任何對象一樣,有它們自己的類,Class類即是Class類的實例。
  • 與其它的對象一樣,類也有方法。對象的方法即是其所屬類的實例方法。亦即,任何一個類的方法就是Class類的實例方法。
  • 所有的類有共同的祖先Object類(都是從Object類直接或間接繼承而來),而Object類又繼承自BasicObject類,Ruby類的根本。
  • 類名是常量(Constant)。
  n = Class.new
  puts n.ancestors
  puts n.supperclass
  puts n.supperclass.supperclass
  puts n.supperclass.supperclass.supperclass

打開類

其實這個就跟方法重定義是一樣的結果,不過隨意改動可能會產生嚴重的后果,比如說你改的這個方法在其它地方有使用到,所以這種方法還是慎用,除非你非常明確該方法不會造成其它后果。

puts 'abc'.replace('a') # a
class String
  def replace(string)
    puts '重新打開了類'
  end
end
'abc'.replace('a')  #'重新打開了類'

我們也可以使用細化來實現這個過程

細化

module StringExtensions
  refine String do
    def replace(string)
       puts '細化'
    end
  end
end

在需要使用這個方法的地方使用using

如:using StringExtensions
細化的好處就是不會全局影響,在你需要使用的地方using就可以了,風險相對較小。

調用方法

類中的方法是怎么調用的?

  • 方法的查找(接收者和祖先鏈)
    Ruby中要在類中查找一個方法,首先在它的類查找這個方法,如果沒有,則往上查找,如此類推,直到祖先鏈的頂端,到最后,如果還沒找到,會拋出method_missing異常。如果有了解過JS,那么你肯定非常明白這個過程,因為JS中的方法查找也是類似于這個過程。
  • 執行方法
    在執行方法的過程中,Ruby始終需要一個接收者的引用,也就是self

self關鍵字

任何時刻,Ruby中只有一個對象能充當當前對象,并且沒有哪個對象能長期充當這個角色,調用一個方法時,接收者就成為了self,從這一刻起,所有的實例變量都是self的實例變量,所有沒有明確指明接收者的方法都在self上調用。
舉個栗子:

class Book
  def get_library
    @book_count = 1000
    self
  end

  def self.is_my_book?(book)
    false
  end
end
b = Book.new
b.get_library # 這個時候,b就充當了self
b.is_my_book?('Ruby元編程') # undefined method `is_book?' for #<Book:0x00000002b92268 @library=1000> (NoMethodError)
Book.is_my_book?('Ruby元編程') # false

上面調用is_my_book?的方法為什么會報錯?
那是因為 self.is_my_book?(book) 等于 Book.is_my_book?(book)
當b調用的時候,self引用b實例對象,不等于Book,所以就會拋出找不到方法的錯誤

方法

  • 動態派發(調用方法:對象.send(方法名,參數))
class Book
  def create_book
    'Ruby元編程'  
  end  
  
  def update_book  
    'Ruby元編程'  
  end  
  
  def delete_book
    'Ruby元編程'    
  end  

  def search_book
    'Ruby元編程'  
  end
end  
  
s = Book.new  
  
puts s.send(:get_one_name)   
puts s.send(:get_two_name)  
puts s.send(:get_three_name) 
puts s.send(:get_four_name)  
  • 動態定義
class Book
  ['create', 'update', 'delete', 'search'].each do |item|
    define_method("#{item}_book"){
      puts "#{item}-Ruby元編程"
    }
  end
end
b = Book.new
b.create_book # create-Ruby元編程
b.update_book # update-Ruby元編程
b.delete_book # delete-Ruby元編程
b.search_book # search-Ruby元編程
  • method_missing(幽靈方法)
# encoding: utf-8
class Book
  def method_missing(name, *argc)
    if [:create_book, :update_book, :delete_book, :search_book].include?(name)  
      puts "#{name}-Ruby元編程" 
    else
      super  
    end
  end
end
b = Book.new
b.create_book# create-Ruby元編程
b.update_book# update-Ruby元編程
b.delete_book # delete-Ruby元編程
b.search_book# search-Ruby元編程
b.book # undefined method `book'

代碼塊

...

類宏

如果按照以前的做法,定義一個屬性的讀寫必須將每個屬性定義一個Get 和 Set方法,比如如下代碼

class Post
  def title=(title)
    @title = title
  end
  def title
    @title
  end
 ....
 ....

如果像一篇文章這樣,定義title,content,author等屬性,就需要寫3組這樣的方法,非常不方便。這個時候,就要亮出Ruby的類宏attr_accessor(module的類里面的一個C語言寫的方法,附上超鏈接,以上代碼就可以寫成

  class Post
    attr_accessor :title
  end

Eval方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內容