偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

初探 Ruby Metaprogramming

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

51CTO推薦專題:Ruby On Rails開發(fā)教程

Classes are open

我們先看一段代碼:

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

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

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

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

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

所有我們毋需擔(dān)心,我們對于to_s的調(diào)用出問題。

前面我說道,ruby的open class比.NET提供的擴(kuò)展方法更加靈活。而這個(gè)靈活體現(xiàn)在我們可以針對一個(gè)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這個(gè)ENV對于我們的程序會有完全不一樣的行為。這里也許有人會說靜態(tài)語言的條件編譯同樣能完成這樣的任務(wù)。那么我們就再看一段代碼

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

執(zhí)行這段代碼,我們會看到這樣的輸出結(jié)果:

Hello 
3

為什么會輸出Hello呢?因?yàn)閐efinition are active,也就是定義本身就是一段可執(zhí)行的代碼。為什么會輸出3呢?因?yàn)閞uby中所有的可執(zhí)行代碼都會有返回值。到這里肯定會有人問,那么class定義中的method呢?你可以試試在irb中定義一個(gè)method,你會發(fā)現(xiàn)在irb會返回一個(gè)nil給你。

但是definition are active在我們實(shí)際開發(fā)中有什么用呢?那讓我們看一下一個(gè)rails的應(yīng)用

  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, 還會有這樣優(yōu)雅的代碼嗎?

All methods have a receiver

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

ruby代碼的執(zhí)行是與當(dāng)前代碼所在context相關(guān),不同的context關(guān)聯(lián)不同的receiver。也就是當(dāng)你的代碼在不同的context下執(zhí)行,由于context關(guān)聯(lián)的receiver不同也就有了不同的結(jié)果。

  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 

結(jié)果為:

"Context"
 "smith"

如果你想知道在你當(dāng)前context下你方法的receiver,可以通過在當(dāng)前context下調(diào)用self來獲得。

Class are Object

我們都知道一個(gè)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" 

對于這個(gè)例子中,p具有什么樣的行為和屬性是由Person這個(gè)class決定的??墒俏覀兛吹綄τ赑erson我們調(diào)用了一個(gè)new的方法,那么這個(gè)new方法是由誰定義的呢?很簡單啊,我們知道p的行為和屬性由它的class也就是Person決定,那么Person的new方法應(yīng)該也來自它的class。也就是引出了Class對象,Class對象中有兩個(gè)new方法,一個(gè)是class method另一個(gè)是instance method。我們的Person.new自然調(diào)用的就是Class對象中叫new的instance method, 那么那個(gè)叫做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 

這段代碼可以實(shí)現(xiàn)之前那段代碼一摸一樣的功能,而這里調(diào)用的就是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,一個(gè)典型“雞生蛋,蛋生雞”的問題。這個(gè)問題給我最大困惑則是:如果我調(diào)用一個(gè)對象例如上面例子中p的XX方法,而這個(gè)XX方法并沒有直接在Person中定義,那么這個(gè)XX方法是來自Class還是Object呢?而對于這一點(diǎn)ruby的解決辦法是在方法的查找receiver的時(shí)候,會先檢查Person有沒有這個(gè)XX方法,會先檢查Class后檢查Object,也就是先檢查一個(gè)class的class,然后檢查superclass。
 

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

【編輯推薦】

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

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關(guān)鍵字yiel

2010-09-08 17:26:46

JavaScript

2017-05-29 08:18:11

Serverless架構(gòu)軟件系統(tǒng)

2013-09-09 09:41:34

2011-09-14 14:15:25

IBMAIX 7操作系統(tǒng)

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

2021-04-14 09:33:58

Kubernetes通信網(wǎng)絡(luò)模型

2014-11-05 11:05:15

Ruby
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號