成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

初探 Ruby Metaprogramming

開發 前端 后端
接觸了一段時間得ruby on rails,深深被ror的magic,powerful,elegantly所折服,同時也對ruby這個神奇的語言本身產生了很大的好奇心,而其中最神奇的莫過于ruby 的 Metaprogramming。

51CTO推薦專題:Ruby On Rails開發教程

Classes are open

我們先看一段代碼:

  1. class String 
  2.   def say_hello  
  3.     p "Hello!" 
  4.   end 
  5. end 
  6.  
  7. "Fred".say_hello 

這里我們看到我們reopen了String這個build-in的class,而且添加了一個新的方法say_hello(.NET 3.5中通過擴展方法也實現了這個特性,但ruby的實現更加自然和靈活)這樣使得ruby語言自身提供了很大的可擴展性,而這種從編程語言層面提供的可擴展性為好處體現在兩個方面。

第一,對于ruby語言自身,在其以后的版本中可以對原有類在不破壞原有代碼的基礎之上提供更多更好的方法。.NET 3.5 已經通過擴展方法這個新特性,在原有集合類的方法之外增加了一些新的查詢方法。

第二,對于ruby的使用者,也就是我們這些ruby程序員來說。classes are open,這就意味我們可以更加實現我們一些具體的特殊的需求。例如,我們希望我們應用的程序中的String都可以提供一個encrype的方法,來實現加密。又或者我們對于String類的to_s方法的實現覺得不夠滿意,我們都可以reopen String這個類,然后定義我們的方法。因為ruby的方法查找遵循

”Define a method twice inside the same class, the second method definition takes precedence“

所有我們毋需擔心,我們對于to_s的調用出問題。

前面我說道,ruby的open class比.NET提供的擴展方法更加靈活。而這個靈活體現在我們可以針對一個instance去增加方法,如下

  1. <SPAN style="FONT-FAMILY: 黑體">fred = 'fred' 
  2. def fred.say_hello  
  3.   p 'hello' 
  4. end 
  5.  
  6. fred.say_hello  
  7. </SPAN> 

這樣就滿足了我們對于一些特殊instance的需求。

Definition are active

  1. class Logger  
  2.   if ENV['debug']  
  3.     def log   
  4.       'debug' 
  5.     end 
  6.   else 
  7.     def log  
  8.       'non-debug' 
  9.     end 
  10.   end 
  11. end 

這是一段非常簡單的代碼,但是我們可以看到我們是否定義debug這個ENV對于我們的程序會有完全不一樣的行為。這里也許有人會說靜態語言的條件編譯同樣能完成這樣的任務。那么我們就再看一段代碼

  1. <SPAN style="FONT-FAMILY: 黑體">result = class Fred  
  2.   puts 'Hello' 
  3.   x = 3  
  4. end 
  5.  
  6. puts result  
  7. </SPAN> 

執行這段代碼,我們會看到這樣的輸出結果:

Hello 
3

為什么會輸出Hello呢?因為definition are active,也就是定義本身就是一段可執行的代碼。為什么會輸出3呢?因為ruby中所有的可執行代碼都會有返回值。到這里肯定會有人問,那么class定義中的method呢?你可以試試在irb中定義一個method,你會發現在irb會返回一個nil給你。

但是definition are active在我們實際開發中有什么用呢?那讓我們看一下一個rails的應用

  1. module ActiveRecord  
  2.   class Base  
  3.     def has_many models  
  4.         
  5.     end 
  6.       
  7.     def belongs_to model  
  8.         
  9.     end 
  10.       
  11.   end 
  12. end 
  13.  
  14. class Order < ActiveRecord::Base  
  15.   has_many :items 
  16. end 
  17.  
  18. class Item < ActiveRecord::Base  
  19.   belongs_to :order 
  20. end 

你能想想如果definition aren't activity, 還會有這樣優雅的代碼嗎?

All methods have a receiver

在ruby中,方法的調用是以message的形式發送給相應的instance的。比如說foo.hello(),就是發送hello這個message給foo。這里很多人會好奇,那么如果我在irb上直接定義方法呢?其實ruby里面有一個概念叫top level execution, 它是一個Object的instance叫做main。當你直接在irb中定義一個方法或者執行一個方法(例如puts "hello"),同樣你只是發送了一個message,而這個message的receiver就是top level execution。

ruby代碼的執行是與當前代碼所在context相關,不同的context關聯不同的receiver。也就是當你的代碼在不同的context下執行,由于context關聯的receiver不同也就有了不同的結果。

  1. class Context  
  2.   def name  
  3.     "smith" 
  4.   end     
  5.   p name      
  6.   def hi  
  7.     p name  
  8.   end 
  9. end  
  10. Context.new.hi 

結果為:

"Context"
 "smith"

如果你想知道在你當前context下你方法的receiver,可以通過在當前context下調用self來獲得。

Class are Object

我們都知道一個object有什么樣的行為和屬性是在ruby中由它的class決定。比如

  1. class Person  
  2.   attr_reader :name 
  3.     
  4.   def initialize(name)  
  5.     @name = name  
  6.   end 
  7.     
  8.   def introduce  
  9.     "I'm #{@name}." 
  10.   end 
  11. end 
  12.  
  13. p = Person.new "Dave" 

對于這個例子中,p具有什么樣的行為和屬性是由Person這個class決定的。可是我們看到對于Person我們調用了一個new的方法,那么這個new方法是由誰定義的呢?很簡單啊,我們知道p的行為和屬性由它的class也就是Person決定,那么Person的new方法應該也來自它的class。也就是引出了Class對象,Class對象中有兩個new方法,一個是class method另一個是instance method。我們的Person.new自然調用的就是Class對象中叫new的instance method, 那么那個叫做new的class method有什么用呢?

  1. Person = Class.new do 
  2.   attr_reader :name 
  3.     
  4.   def initialize(name)  
  5.     @name = name  
  6.   end 
  7.     
  8.   def introduce  
  9.     "I'm #{@name}." 
  10.   end 
  11. end 

這段代碼可以實現之前那段代碼一摸一樣的功能,而這里調用的就是Class中叫做new的class method。最奇怪的Class的superclass是Module,而Module的superclass是Object,但是Class的class是自身,Module的class是Class,而Object的class也是Class(superclass是Class的方法,class是Object的方法),我們也可以說ruby中所有的Object的class都是Class(nil的class是NilClass,但是NilClass的class是Class)。Class間接繼承Object,但是Object的class又是Class,一個典型“雞生蛋,蛋生雞”的問題。這個問題給我最大困惑則是:如果我調用一個對象例如上面例子中p的XX方法,而這個XX方法并沒有直接在Person中定義,那么這個XX方法是來自Class還是Object呢?而對于這一點ruby的解決辦法是在方法的查找receiver的時候,會先檢查Person有沒有這個XX方法,會先檢查Class后檢查Object,也就是先檢查一個class的class,然后檢查superclass。
 

原文鏈接:http://www.cnblogs.com/feihe/archive/2011/04/17/1951274.html

【編輯推薦】

  1. 關于Ruby/RoR我的體驗和看法
  2. 橫向壓力測試:Ruby on Rails PK CakePHP
  3. 在Nginx上運行Ruby on Rails
  4. 解讀Ruby on Rails的成功秘籍
  5. 加速Ruby on Rails 消除N+1查詢問題
責任編輯:陳貽新 來源: Fei He's Blog
相關推薦

2009-06-24 13:22:27

Glassfish

2010-06-03 12:57:06

Hadoop

2016-10-11 13:48:41

WebGLJavascriptWeb

2009-12-18 11:22:34

Ruby source

2014-11-20 15:44:40

Apple Watch

2015-01-21 16:35:49

Apple WatchWatchKit

2012-02-29 15:03:30

2011-05-17 14:11:06

Dijkstra

2009-12-18 11:37:54

Ruby關鍵字yiel

2014-11-05 11:05:15

Ruby

2009-08-27 10:21:22

Ruby on Rai

2010-09-08 17:26:46

JavaScript

2017-05-29 08:18:11

Serverless架構軟件系統

2013-09-09 09:41:34

2011-09-14 14:15:25

IBMAIX 7操作系統

2011-06-16 10:25:29

AndroidAIR

2011-08-24 09:30:29

JavaJVM

2012-04-05 13:50:38

Java

2012-07-09 10:22:28

Mono for An

2013-04-10 11:23:27

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: av黄色在线 | 特级特黄特色的免费大片 | 精品日韩欧美一区二区 | 亚洲精品888 | 五月激情综合 | av天天干 | 日本久久一区二区三区 | 狠狠的操 | 亚洲成人999 | 麻豆changesxxx国产 | 成人美女免费网站视频 | 亚洲国产精品久久久久秋霞不卡 | 日韩精品在线免费观看 | 国产精品毛片无码 | 日韩欧美国产精品 | 综合色影院 | 福利片在线观看 | 亚洲国产精品久久久 | 狠狠色综合网站久久久久久久 | 欧美亚洲激情 | 亚洲字幕在线观看 | www国产精| 中文日韩字幕 | 久久久国产一区二区三区 | 亚洲精品18 | 国产小视频在线观看 | 一区视频 | 亚洲福利一区 | 日本特黄a级高清免费大片 成年人黄色小视频 | 日本三级精品 | 日韩精品免费在线 | 日韩视频一区二区在线 | 亚洲成人免费视频在线观看 | 一区二区三区国产 | 日韩免费视频一区二区 | 国产精品日韩欧美一区二区三区 | 国产精品久久久久久久久动漫 | 亚洲精品9999 | 羞羞视频一区二区 | 在线国产一区二区 | 日韩av在线中文字幕 |