乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      .NET程序員新方向 Ruby核心語法入門

       燮羽 2011-04-22

        本文的目的是為了找出為什么.NET程序員都想學習并使用Ruby,并探索Ruby語言的核心語法。

        微軟的IronRuby項目為Windows平臺帶來了強大的動態(tài)語言,Ruby編程語言是一個現(xiàn)代的,面向?qū)ο蟮幕菊Z言,它的語法靈感來自Perl和Smalltalk語言,它是由一名日本人松本行弘(外號Matz)發(fā)明的,用他的話說,他是想發(fā)明一種語言比Perl更強大,同時比Python更面向?qū)ο蟮木幊陶Z言,在“http://www./pub/a/linux/2001/11/29/ruby.html”有一篇對松本行弘專訪文章,大家可以去看看。于是Ruby被設(shè)計為非常貼近自然語言,作者的原意就是要減少編程時候的不必要的瑣碎時間,令編寫程序的人高興,他于1996年發(fā)布了1.0版本。

        這么多年來,Ruby一直鮮為人知,但它的功能已經(jīng)遠遠超出了最初設(shè)計時的想法:以最簡化的方法操作數(shù)據(jù)和環(huán)境。我第一次“玩”它還是在幾年前,那時我正在尋找一種替換處理自動管理任務(wù)的批處理文件的方法。

        Ruby真正開始流行還得從一個來自伊利諾斯洲芝加哥市的名叫37signals小公司說起,它們發(fā)布了一個名叫Rails的Web應(yīng)用程序框架,這個新的框架吸取了已經(jīng)被證明是可靠的Model-View-Controller和ActiveRecord模型的經(jīng)驗,并且添加了一些新的思想,如convention over configuration,導致它實現(xiàn)了太多的目標,幾乎不需要編碼了。

        RubyCLR和IronRuby

        在2006年早些時候,John Lam發(fā)布了一個開源項目,叫做RubyCLR,它在Ruby和.NET之間起到一個橋梁的作用,它允許用戶可以直接從Ruby訪問.NET平臺豐富的資源,甚至將Ruby對象都暴露給CLR了,這個項目非常有雄心,但它沒有打算將Ruby向.NET靠攏,而是打算讓這兩個世界相互對話,你仍然需要在你的機器上按照Ruby運行時環(huán)境。

        RubyCLR項目為人們理解如何將Ruby和.NET和諧地溶合到一起邁出了關(guān)鍵的第一步,John的工作沒有引起人們的注意,2006年末,他在他的博客上宣布加入微軟新成立的動態(tài)語言運行時環(huán)境(DLR)團隊,在John宣布前幾個月,微軟發(fā)布了IronPython的1.0版本,它是Python語言在.NET框架上一個新的實現(xiàn),動態(tài)語言運行時環(huán)境在IronPython上工作,它在.NET框架構(gòu)建了一個運行環(huán)境,允許動態(tài)語言進入.NET。

        John和他的團隊在2007年的MIX大會上宣布了IronRuby,可能真正讓人吃驚的是IronRuby項目本身是微軟的第一個真正意義上的開源.NET語言,不僅可以得到源代碼,而且還可以獲取來自社區(qū)的貢獻。

        IronRuby仍然處于發(fā)展階段,然而偶然也會刪掉已經(jīng)可以利用的東西,這些東西通常是其它項目的一部分,如最近發(fā)布的Silverlight 2.0 Beta 2,這些后續(xù)的項目也放在源代碼樹中了,并且也有相應(yīng)的郵件列表。

        為什么要學習Ruby?

        我最喜歡的一本書叫做《程序員實務(wù):從熟練工到大師》【英文名是《The Pragmatic Programmer: From Journeyman to Master》】,該書的作者鼓勵程序員每年學習一門新的編程語言,對于我而言,當我學習了Ruby語言后,大大地改變了我的專業(yè)范圍。

        Ruby是一門完全面向?qū)ο蟮恼Z言,這意味著在系統(tǒng)中每一樣打交道的東西都是對象,包括直接的值,如數(shù)字,即使是類,也是由新創(chuàng)建的對象實例組成的模板。

        因為Ruby是一個動態(tài)語言,你會發(fā)現(xiàn)類型已經(jīng)變得不太重要了,當一個類函數(shù)以參數(shù)形式獲取到一個對象時,不需要指定對象需要的類型。實際上,Ruby沒有編譯器,因此,可能直到傳遞給類函數(shù)的對象不滿足方法的需要時,你才會發(fā)現(xiàn)這一點。

        如果你象我?guī)啄昵澳菢?,你也許會發(fā)現(xiàn)這個概念讓你不安,如果沒有編譯器,那么你可能要盡可能最快地在運行前就了解代碼中的錯誤,而不用等到運行時才知道。如果你還是習慣于讓編譯器告訴你錯誤,那你就不用選擇Ruby了。
        正是由于以前編譯器能夠報告錯誤,如類型不匹配,當你編寫一個類函數(shù)時,你可能希望“這里的對象必須能夠做到foo和bar”,然后創(chuàng)建一個接口叫做IFooBar,看起來這是一個不錯的解決方案,但當你想使用其它的在IfooBar之前創(chuàng)建的類時(特別是那些來自框架的類型),你就會失敗了。

        作者提醒:IronRuby還沒有成為主流的工具,你可以使用Ruby的標準版本進行學習,如果你想實驗后面的例子,可以從http://rubyinstaller./下載。

        Ruby示例

        學習Ruby或一門新的編程語言最好的方法就是多練習,研究它的交互接口,大多數(shù)動態(tài)語言都有交互提示符,稱之為讀-執(zhí)行-打印環(huán)(即REPL,Read-Execute-Print Loop),Ruby中的REPL程序叫做irb(即交互式Ruby,interactive Ruby)。

        當你執(zhí)行irb程序時,你會看到一個irb提示符,如:

        C:\Users\Brad> irb
                        irb(main):001:0>
                        

        當你在irb提示符后敲入命令時,Ruby解釋程序就會評估它們,并將結(jié)果輸出到你屏幕上,與irb類似的REPL是學習一門語言的優(yōu)秀方法:每次一條語句。

        下面對irb做一個簡單的介紹,在irb提示符后,敲入5+2,并回車,告訴Ruby計算這個表達式的值:

        irb(main):001:0> 5 + 2
                        => 7
                        

        irb(main):001:0>部分是irb的提示符,當你敲入5+2并回車時,irb就將結(jié)果輸出到屏幕上,如這里的=> 7,=> 是irb顯示輸出結(jié)果時使用的提示符。

        如果Ruby認為你還沒有完成表達式的書寫,它允許你繼續(xù)換行書寫,如當你敲入5+2+時就按了回車,Ruby認為你還有一部分沒有輸入完畢,它會繼續(xù)讓你在下一行輸入,如:

        irb(main):002:0> 5 + 2 +
                        irb(main):003:0* 13
                        => 20
                        

        第二行的提示符變?yōu)樾翘枺?)了,而不是“>”,這樣你就知道你在完成前面沒有完成的表達式。

        基礎(chǔ)類型

        如果一門編程語言不能處理數(shù)字,那就不值得學習和使用,Ruby當然能夠滿足算術(shù)運算了,如:

        irb(main):004:0> 3 + 4
                        => 7
                        irb(main):005:0> 3 * 4
                        => 12
                        irb(main):006:0> 3 - 4
                        => -1
                        irb(main):007:0> 3 / 4
                        => 0
                        irb(main):008:0> 3.0 / 4.0
                        => 0.75
                        irb(main):009:0> 0xF
                        => 15
                        irb(main):010:0> 0x3 * 0xA
                        => 30
                        

        正如你所看到的,Ruby支持整數(shù)和浮點類型,甚至可以接收常用的十六進制整數(shù),但0x3 * 0xA的結(jié)果是以十進制的形式顯示的,即顯示結(jié)果是30而不是0x1E。

        因為在.NET中,數(shù)字也是真實的對象,因此,你可以在它們上面調(diào)用類函數(shù),如:

        irb(main):011:0> 14.to_s
                        => "14"

        在c++中不要這樣做。

        to_s類函數(shù)的功能是將一個對象轉(zhuǎn)換成一個字符串,因此,14.to_s返回的結(jié)果是"14",和.NET中的to_string()函數(shù)一樣,to_s函數(shù)實際上是一個對象函數(shù),因此,在Ruby中你可以將任何東西轉(zhuǎn)換成字符串。

        字符串

        Ruby的字符串具備完整的操作支持,如:

        irb(main):012:0> "hello" + "there"
                        => "hellothere"
                        irb(main):013:0> "Reader".length
                        => 6
                        irb(main):014:0> "Reader".reverse
                        => "redaeR"
                        irb(main):015:0> "reader".capitalize
                        => "Reader"
                        irb(main):016:0> "Reader".include?("foo")
                        => false
                        irb(main):017:0> "Reader".include?("ade")
                        => true
                        irb(main):018:0> "  Reader  ".strip
                        => "Reader"
                        irb(main):019:0> "Reader".gsub("e", "f")
                        => "Rfadfr"
                        irb(main):020:0> "Reader".delete("ea")
                        => "Rdr"
                        irb(main):021:0> "a" < "b"
                        => true
                        

        幾乎可以使用所有的字符串操作符,可能有的你還從來都沒有使用過,如下面的代碼按字母順序測試某個字符串是否位于其他兩個之間:

        irb(main):022:0> "Bob".between? "Adam", "Chris"
                        => true
                        

        乘法操作符可以讓給定的字符串重復顯示指定的數(shù)量,如:

        irb(main):023:0> "hi" * 5
                        => "hihihihihi"
                        

        Crypt函數(shù)為字符串提供了一個單向哈希加密功能,在存儲敏感數(shù)據(jù)如密碼時就可以使用它,如:

        irb(main):024:0> "Reader".crypt("ab")
                        => "abofgDjq6JNJo"
                        

        字符

        Ruby沒有內(nèi)置的字符類型,它象數(shù)字一樣表現(xiàn)字符,可以是?語法來表示一個字符常量,你可以使用chr函數(shù)將一個數(shù)字轉(zhuǎn)換成一個等價的字符串,如:

        irb(main):025:0> "Reader"[2]
                        => 97
                        irb(main):026:0> ?a
                        => 97
                        irb(main):027:0> 97.chr
                        => "a"
                        

        賦值

        其實執(zhí)行這個操作并沒什么用途,除非你可以將其存儲起來方便后面使用,如:

        irb(main):028:0>x = 42
                        =>42
                        

        字符串有一個特殊的語法,允許嵌入式賦值,這個賦值不僅僅局限于簡單的變量替換,它是一個完整的賦值,如:

        irb(main):029:0> "The answer is #{x}!"
                        => "The answer is 42!"
                        irb(main):030:0> "The answer is #{6 * 7}!"
                        => "The answer is 42!"
                        

        可以使用單引號將字符串引起來避免這種賦值,注意是單引號,不是雙引號,如:

        irb(main):031:0> 'The answer is #{x}!'
                        => "The answer is \#{x}!"
                        

        數(shù)組

        Ruby中的數(shù)組與.NET 1.0中的ArrayList類很接近,它們的大小都是可變的,用于存儲任意類型的數(shù)據(jù),從0開始編號,如:

        irb(main):032:0> a = ["hello", 42, "world"]
                        => ["hello", 42, "world"]
                        irb(main):033:0> a << 5.0 * 7.5
                        => ["hello", 42, "world", 37.5]
                        irb(main):034:0> a[0]
                        => "hello"
                        irb(main):035:0> a[6] = 'hi' * 2
                        => "hihi"
                        irb(main):036:0> a
                        => ["hello", 42, "world", 37.5, nil, nil, "hihi"]
                        irb(main):037:0> a[99]
                        => nil
                        

        前面的代碼顯示了如何使用<<操作符向數(shù)組末尾追加項目,以及獲取或設(shè)置值使用的指針操作符[],當你向數(shù)組末尾添加一個項目時,Ruby使用零值填充數(shù)組中的“洞”,當你訪問數(shù)組外的值時,Ruby返回零值而不是異常。

        你可以使用一個范圍的指針將數(shù)組分片,也可以使用負的指針從后向前訪問數(shù)組,-1就是最后一項,-2是倒數(shù)第二項,以此類推,但不能使用反向范圍獲取反向分片,你可以使用一個正向范圍,然后調(diào)用reverse方法,如:

        irb(main):038:0> a[-1]
                        => "hihi"
                        irb(main):039:0> a[1..3]
                        =>[42, "world", 37.5]
                        irb(main):040:0>a[2..-2]
                        =>["world", 37.5, nil, nil]
                        irb(main):041:0>a[-4..-1]
                        =>[37.5, nil, nil, "hihi"]
                        irb(main):042:0>a[-1..-4]          # 不能工作
                        =>[]
                        irb(main):043:0>a[-4..-1].reverse  # 能夠工作
                        =>["hihi", nil, nil, 37.5]
                        

        和字符串一樣,你會發(fā)現(xiàn)有多個唯一對數(shù)組有用的類函數(shù),如:

        irb(main):044:0> a
                        => ["hello", 42, "world", 37.5, nil, nil, "hihi"]
                        irb(main):045:0> a.compact
                        => ["hello", 42, "world", 37.5, "hihi"]
                        irb(main):046:0> a.join
                        => "hello42world37.5hihi"
                        irb(main):047:0> [10, 75, 6, 29].sort
                        => [6, 10, 29, 75]
                        irb(main):048:0> [[1, 2, 3], [4, 5, 6]]
                        => [[1, 2, 3], [4, 5, 6]]
                        irb(main):049:0> [[1, 2, 3], [4, 5, 6]].flatten
                        => [1, 2, 3, 4, 5, 6]
                        

        散列

        Ruby的最后一個核心數(shù)據(jù)結(jié)構(gòu)是散列,與.NET 1.0中的散列表類似,它是一個聯(lián)合數(shù)組,它的鍵值可以是任意類型的值,它們指向的數(shù)據(jù)也可以是任意類型的數(shù)據(jù),實際上,大部分散列使用的是符號作為鍵值。

        使用{}語法聲明散列,并且使用key => value格式聲明初始值,在散列中獲取或設(shè)置值時都可以使用鍵值操作符,如:

        irb(main):050:0> h = {:foo=>'bar', :baz=>'biff'}
                        => {:foo=>"bar", :baz=>"biff"}
                        irb(main):051:0> h[:foo]
                        => "bar"
                        irb(main):052:0> h[:unknown]
                        => nil
                        irb(main):053:0> h[:baz] = "new"
                        => "new"
                        => {:foo=>"bar", :baz=>"new"}
                        irb(main):054:0> h.entries
                        => [[:foo, "bar"], [:baz, "new"]]
                        

        變量

        Ruby中的變量和類函數(shù)名都是以小寫字母開頭的,可以包括字母、數(shù)字和下劃線。本地變量沒有前綴,實例變量以@開頭,全局變量以$開頭。
        在使用變量前無需聲明,未初始化的變量有一個零值,下面是幾個預定義的變量:

        nil表示一個“無”對象,與.NET中的null類似,除了nil是一個實例化的NilClass類外。

        true和false分別是實例化的TrueClass和FalseClass。

        在類函數(shù)中使用時,self指向調(diào)用類函數(shù)的對象實例;在一個類中使用時,它指的是實例化的類對象本身。

        __FILE__ 和__LINE__返回當前執(zhí)行文件和那個文件中的行號。

        符號

        Ruby有一個特殊類型的字符串,叫做符號,因為字符串在Ruby中是可以被修改的,使用它們作為散列鍵是很慢的,而且有一些情況是不能預測的。
        除了它們是以冒號(:)開頭外,符號的命名規(guī)則和變量的命名規(guī)則一致,你不能改變符號的值,兩個名字相同的符號它們的身份就一樣,它們可以作為優(yōu)秀的散列鍵,查找請求只需要比較整數(shù)值,而不是與一個可變長字符串的值進行對比。

          Ruby中的所有事物都是對象,所有對象都是類的實例,為了探索類是個什么東西,在它上面調(diào)用類函數(shù):

          5.class
                              => Fixnum
                              (2 ** 96).class
                              => Bignum
                              7.5.class
                              => Float
                              (1..10).class
                              => Range
                              "foo".class
                              => String
                              /^foo[a-e]$/.class
                              => Regexp
                              :foo.class
                              => Symbol
                              [].class
                              => Array
                              {}.class
                              => Hash
                              

          塊和閉包

          雖然這與.NET 1.X中的事件處理程序類似,但當你想處理它們時還是必須要定義完整的類函數(shù)來連接這些事件,這就導致需要創(chuàng)建大量的類函數(shù),因為框架需要它。

          .NET 2.0引入了匿名委派的概念,它們起的作用與Ruby中的塊類似,如:

          irb(main):001:0> h = {:foo=>'bar', :hi=>'there'}
                              => {:foo=>"bar", :hi=>"there"}
                              irb(main):002:0> h.each_key {|k| puts k}
                              foo
                              hi
                              => {:foo=>"bar", :hi=>"there"}
                              irb(main):003:0> h.each {|k,v| puts "#{k}: #{v}"}
                              foo: bar
                              hi: there
                              => {:foo=>"bar", :hi=>"there"}
                              

          正如你所看到的,Ruby中塊的語法是相當簡潔的:通常使用一對大括號打開塊和關(guān)閉塊,使用|x,y|語法標出傳遞給塊的變量。

          Ruby中的塊和閉包類似,正如.NET 2.0中的匿名委派,這意味著它們有權(quán)訪問它們封裝作用域的值,即使那個作用域退出后也可以訪問。下面是一個將幾個值相乘的閉包示例:

          irb(main):004:0> n = [5, 6, 10]
                              => [5, 6, 10]
                              irb(main):005:0> t = 1
                              => 1
                              irb(main):006:0> n.each { |i| t *= i }
                              => [5, 6, 10]
                              irb(main):007:0> t
                              => 300
                              

          你甚至可以將引用存儲在塊中,方便以后使用,如:

          irb(main):008:0> t = 1
                              => 1
                              irb(main):009:0> f = lambda { |i| t *= i }
                              => #                    < PRE>
                              

          函數(shù)

          Ruby中函數(shù)的定義比.NET簡單多了,因為不需要指定類型,如:

          irb(main):001:0> def greet(name)
                              irb(main):002:1>   puts "Hello, #{name}!"
                              irb(main):003:1> end
                              => nil
                              irb(main):004:0> greet "Reader"
                              Hello, Reader!
                              => nil
                              irb(main):005:0> greet 42
                              Hello, 42!
                              => nil
                              


          Ruby執(zhí)行的某些東西叫做“鴨式輸入”:如果它走起路來像鴨子或聲音也像鴨子,那它一定就是鴨子。你不用問它“你是一只鴨子嗎?”,你只需要將它當做鴨子對它呷呷地叫就可以了,如果你渴望成為一只鴨子,只要你能呷呷地叫的就可以加入這個party。

          注意greet函數(shù)定義時沒有對對象的類型做任何限制,因為它只打印它們—Ruby中任何事物都是支持打印的,這得益于to_s類函數(shù)的優(yōu)點,它可以將任何對象轉(zhuǎn)換成字符串,最終結(jié)果就是你可以greet它們。

          下面是另一個例子:

          irb(main):006:0> def print_len(item)
                              irb(main):007:1>   puts "Len = #{item.length}"
                              irb(main):008:1> end
                              => nil
                              irb(main):009:0> print_len "Reader"
                              Len = 6
                              => nil
                              irb(main):010:0> print_len [1, 4, 9]
                              Len = 3
                              => nil
                              irb(main):011:0> print_len 42
                              NoMethodError: undefined method <span class="pf">'
          </span>length' for
                              42:Fixnum
                              from (irb):7:in <span class="pf">'</span>print_len'
                              from (irb):11

          這里的print_len函數(shù)做的事情更多了:它調(diào)用了length函數(shù)。因此傳遞給print_len的是length函數(shù)的返回值,可以傳遞一個字符串或一個數(shù)組,因為它們都有對應(yīng)的length函數(shù),但是不能傳遞一個數(shù)字,因為沒有對應(yīng)數(shù)字的length函數(shù)。

          為了在.NET中編寫一個類似的函數(shù),你可能需要創(chuàng)建一個IHaveLength接口作為你的參數(shù)類型,由于在你創(chuàng)建接口前類就已經(jīng)創(chuàng)建好了,所以不幸的是,可能你需要創(chuàng)建一個類型轉(zhuǎn)換器。

          從另一方面來看,至少你已經(jīng)有了IHaveLength,并且知道函數(shù)需要什么東西,既然類型擔當?shù)氖悄撤N格式文檔的角色,在動態(tài)語言中你需要一個取舍,這樣你會在編寫文檔和單元測試時更自信,可以幫助你識別類或函數(shù)是如何使用的。

          Ruby支持默認的參數(shù)值,如:

          irb(main):012:0>def repeat(val, times = 5)
                              irb(main):013:1>val.to_s * times
                              irb(main):014:1>end
                              =>nil
                              irb(main):015:0>repeat "hi"
                              =>"hihihihihi"
                              irb(main):016:0>repeat "hi", 3
                              =>"hihihi"
                              irb(main):017:0>repeat 10, 3
                              =>"101010"
                              

          注意在to_s * times前面沒有return,除非你明確地告訴它返回什么值,否則Ruby中的函數(shù)總是返回最后一個賦值,因此就不需要return關(guān)鍵字了。

          Ruby支持變量參數(shù),如:

          irb(main):018:0> def add(*values)
                              irb(main):019:1>   result = 0
                              irb(main):020:1>   values.each {|x| result += x}
                              irb(main):021:1>   result
                              irb(main):022:1> end
                              => nil
                              irb(main):023:0> add 1, 2, 3, 4, 5
                              => 15
                              

          Ruby將變量參數(shù)打包成一個數(shù)組,然后你就可以訪問傳遞來的值,并且可以將它們集合到一塊兒。

          函數(shù)和變量命名約定

          Ruby中的函數(shù)以小寫字母開頭,可以包含字母,數(shù)字和下劃線。改變基礎(chǔ)對象的函數(shù)名稱以一個驚嘆號(!)結(jié)束,例如:upcase函數(shù)返回字符串的大寫,但是還單獨保留了原始字符串;相反,upcase!函數(shù)就真實地改變了基礎(chǔ)字符串。
          回答問題(返回布爾值)的函數(shù)名稱以一個問號(?)結(jié)束。

          類是來自新對象實例創(chuàng)建時的模板,例如:為了將前面的greet函數(shù)放入一個類,你可能要編寫以下代碼:

          irb(main):001:0> class Manners
                              irb(main):002:1>   def greet(name)
                              irb(main):003:2>     puts "Hello, #{name}!"
                              irb(main):004:2>   end
                              irb(main):005:1> end
                              => nil
                              irb(main):006:0> m = Manners.new
                              => #< PRE irb(main):007:0> m.greet ?Reader? Hello, Reader!=">" nil>

          前面的代碼創(chuàng)建了一個新的類,叫做Manners,并將函數(shù)greet添加到該類中了,最后,它創(chuàng)建了一個Manners類的實例,使用它greet Reader。

          你可能認為在Ruby中類是對象的活動模板,與.NET中的類不同,Ruby中的類是編譯時定義的,你可以對其進行任意擴展,當你完成擴展后,類的現(xiàn)有實例也會立即得到新的反應(yīng),注意當你嘗試告訴它farewell時會發(fā)生什么,如:

          irb(main):008:0> m.farewell "Reader"
                              NoMethodError: undefined method 'farewell' for
                              #<Manners:0x404839c>
                              from (irb):8
                              

          當你嘗試調(diào)用farewell時,系統(tǒng)會告訴你它不知道這是什么,那么就可以對Manners類進行擴展,讓它知道這么說拜拜,如:

          irb(main):009:0>class Manners
                              irb(main):010:1>def farewell(name)
                              irb(main):011:2>puts "Goodbye, #{name}!"
                              irb(main):012:2>end
                              irb(main):013:1>end
                              =>nil
                              irb(main):014:0>m.farewell "Reader"
                              Goodbye, Reader!
                              =>nil
                              

          擴展了Manners類后,它的已有實例就會立即獲得這個新的功能。

          Manners類有兩個函數(shù),兩個都需要你的名字,你可能需要重新編寫它以便你創(chuàng)建它時可以傳遞名字給它,Ruby調(diào)用initialize函數(shù),你傳遞的所有參數(shù)都傳遞給new,下面是更新后的Manners類:

            irb(main):001:0> class Manners
                                    irb(main):002:1>   def initialize(name)
                                    irb(main):003:2>     @name = name
                                    irb(main):004:2>   end
                                    irb(main):005:1>   def greet
                                    irb(main):006:2>     puts "Hello, #{@name}!"
                                    irb(main):007:2>   end
                                    irb(main):008:1>   def farewell
                                    irb(main):009:2>     puts "Goodbye, #{@name}!"
                                    irb(main):010:2>   end
                                    irb(main):011:1> end
                                    => nil
                                    irb(main):012:0> m = Manners.new "Reader"
                                    => #< PRE m.greet Hello, Reader!=">" nil @name="Reader" > irb(main):013:0> irb(main):014:0> m.farewell Goodbye,>


          注意類在一個實例變量@name中存儲的名字,同時注意檢查實例包括所有實例變量的值。

          你自己定義的類可以隨意擴展,而且也可以擴展Ruby內(nèi)置的類,如:

          irb(main):001:0> class Array
                              irb(main):002:1>   def print_tr
                              irb(main):003:2>     puts "<tr>"
                              irb(main):004:2>     each { |item|
                              irb(main):005:3*       puts "  <td>#{item}</td>"
                              irb(main):006:3>     }
                              irb(main):007:2>     puts "</tr>"
                              irb(main):008:2>   end
                              irb(main):009:1> end
                              => nil
                              Irb(main):010:0> ["hello","world!"].print_tr
                              <tr>
                              <td>hello</td>
                              <td>world!</td>
                              </tr>
                              => nil
                              

          Rails對內(nèi)置類型添加了許多擴展屬性,提供了非常豐富的接口,例如:你可以編寫類似5.days.from_now這樣的代碼,返回從現(xiàn)在開始5天后的日期。

          迄今為止,你定義的函數(shù)都已經(jīng)成為實例函數(shù),即它們僅在類的實例中有效。Ruby也有靜態(tài)函數(shù),有時也叫做類函數(shù)。實際上,你已經(jīng)調(diào)用過一次靜態(tài)函數(shù)了,那就是new。

          你可以在現(xiàn)有的類上添加任何新的靜態(tài)函數(shù),如:

          irb(main):001:0> def String.concat(s1, s2)
                              irb(main):002:1>   s1 + ' ' + s2
                              irb(main):003:1> end
                              => nil
                              irb(main):004:0> String.concat 'hi', 'bye'
                              => "hi bye"
                              

          你也可以使用self語法在定義或擴展類的上下文中定義它們,如:

          irb(main):001:0> class String
                              irb(main):002:1>   def self.concat(s1, s2)
                              irb(main):003:2>     s1 + ' ' + s2
                              irb(main):004:2>   end
                              irb(main):005:1> end
                              => nil
                              irb(main):006:0> String.concat 'hi', 'bye'
                              => "hi bye"
                              

          反射

          反射是運行時發(fā)現(xiàn)關(guān)于對象的信息的過程,你可以通過調(diào)用methods函數(shù)找到某個類可用的函數(shù),Ruby中的基礎(chǔ)類也是對象,下面是查找在Ruby中對每個對象都有效的函數(shù)的代碼:

          irb(main):001:0> o = Object.new
                              => #<Object:0x3f8feb4>
                              irb(main):002:0> o.methods
                              => ["inspect", "taguri", "clone", "public_methods"
                              , "taguri=", "display", "instance_variable_defined
                              ?", "equal?", "freeze", "methods", "respond_to?",
                              ...many more methods listed...
                              

          調(diào)用methods函數(shù)返回的結(jié)果是一個字符串數(shù)組,包含了那個對象上有效的每個函數(shù)的名字,你也可以認為類與散列非常相似,調(diào)用methods函數(shù)就與獲取散列表的鍵值相似。

          你若不使用函數(shù)做點事情,你會覺得它很無趣,為了調(diào)用函數(shù),你還可以使用send函數(shù),如下面這兩條語句都是等效的:

          irb(main):003:0> o.inspect
                              => "#<Object:0x3f8feb4>"
                              irb(main):004:0> o.send "inspect"
                              => "#<Object:0x3f8feb4>"
                              

          通過在你的類中定義method_missing函數(shù),Ruby讓你有機會處理未知的函數(shù),如:

          irb(main):139:0> class Object
                              irb(main):140:1>   def method_missing(*args)
                              irb(main):142:2>     puts args
                              irb(main):143:2>   end
                              irb(main):144:1> end
                              => nil
                              irb(main):145:0> o.foobar 1, 2, 3
                              foobar
                              1
                              2
                              3
                              => nil
                              

          正如你所看到的,傳遞給method_missing函數(shù)的參數(shù)包括請求的函數(shù)和所有傳遞給那個函數(shù)的參數(shù),一個更好的定義如下:

          def method_missing(method, *args)
                              


          元編程

          即使Ruby沒有屬性,你也可以使用函數(shù)調(diào)用,通常不需要括弧來模擬屬性,你也需要影響Ruby以“=”結(jié)束函數(shù)的特殊處理方式,讓它們擔當調(diào)節(jié)器的作用。

          你可以象下面這樣定義一個person類:

          irb(main):001:0> class Person
                              irb(main):002:1>   def age
                              irb(main):003:2>     @age
                              irb(main):004:2>   end
                              irb(main):005:1>   def age=(value)
                              irb(main):006:2>     @age = value
                              irb(main):007:2>   end
                              irb(main):008:1> end
                              => nil
                              

          接下來就可以使用person類的實例,將age當作person類的一個屬性來處理,如:

          irb(main):009:0>p = Person.new
                              =>#                    < PRE irb(main):011:0>p.age="42" =">nil" irb(main):012:0>p.age=">42">
                              

          如果你想將age的默認值設(shè)為一個非零的值,那么你可以使用initialize函數(shù)來設(shè)置。

          這個代碼顯得非常標準,如果這是一個類似c#的語言,你可能會使用類似Visual Studio中片段,甚至靜態(tài)代碼的產(chǎn)生會自動生成reader和writer的屬性。
          在Ruby中,你可以使用元編程做一點努力就可以創(chuàng)建這些事物,理想情況下,你可以編寫類似下面這樣的代碼:

          class Person
                              prop :age
                              end

          你應(yīng)該在對象上定義個類(靜態(tài))函數(shù)以便你在定義自己的類時可以使用它,你也可以使用一個你還沒有看到過的函數(shù),class_eval函數(shù),如:

          irb(main):001:0> class Object
                              irb(main):002:1>   def self.prop *names
                              irb(main):003:2>     names.each { |name|
                              irb(main):004:3*       self.class_eval "
                              irb(main):005:3"         def #{name}
                              irb(main):006:3"           @#{name}
                              irb(main):007:3"         end"
                              irb(main):008:3>       self.class_eval "
                              irb(main):009:3"         def #{name}=(value)
                              irb(main):010:3"           @#{name} = value
                              irb(main):011:3"         end"
                              irb(main):012:3>     }
                              irb(main):013:2>     nil
                              irb(main):014:2>   end
                              irb(main):015:1> end
                              => nil
                              

          上面使用的class_eval函數(shù)是創(chuàng)建了另外一個函數(shù)結(jié)束的,它給字符串賦值,因此你可以在你的類中編寫自己的函數(shù)。

          每個傳遞給prop函數(shù)的名字向新類添加了兩個函數(shù):getter和setter。最終使用你傳遞給prop的名字替換掉#{name}。

          接下來,你可以在你的類定義中使用prop了,如:

          irb(main):016:0> class Person
                              irb(main):017:1>   prop :age, :name
                              irb(main):018:1>
                              irb(main):019:1*   def initialize(age, name)
                              irb(main):020:2>     @age = age
                              irb(main):021:2>     @name = name
                              irb(main):022:2>   end
                              irb(main):023:1> end
                              => nil
                              irb(main):024:0> p = Person.new(36, "Brad")
                              => #
                              < PRE @name="Brad" > @age="36," irb(main):025:0> p.age=">" 36 irb(main):026:0> p.name=">" ?Brad?>
                              

          在你的環(huán)境中有了這些便利的工具后,你可以更快速地創(chuàng)建更高層次的類,使用這些元編程技巧可以幫助你工作得更好,不需要依賴于編輯片段或編譯時代碼生成。

          小結(jié)

          本文只是對Ruby中便利工具做了一個皮毛介紹,今天學習好Ruby可以在當Ruby..NETSilverlight中可用時幫助你,有這么強大的一個動態(tài)編程語言,你的編程工具箱也會擴寬許多,但更重要的是,它可以幫助你開始以一種新的方式思考問題和解決方案。


        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多