ruby 存取器

来源:互联网 发布:华南师范网络教育证书 编辑:程序博客网 时间:2024/05/22 07:02

甚麼是存取器?

我們曾在之前的章節討論過實例變數,但尚未深入探討。物件的實例變數即是物件的屬性 (attribute),用以區分出同類別的其他物件。能夠讀寫這些屬性非常重要,若要讀寫便需要稱為屬性存取器 (attribute accessors) 的公開方法(編註:所有實例變數都不公開的,除非透過公開方法存取)。我們等一下就會看到,並不是每次都需要明確地寫出存取器方法,現在先看一下所有的步驟。兩種存取器分別是寫入器 (writer)閱讀器 (reader)

ruby> class Fruit
    |   def set_kind(k)  # 寫入器
    |     @kind = k
    |   end
    |   def get_kind     # 閱讀器
    |     @kind
    |   end
    | end
   nil

ruby> f1 = Fruit.new
   #<Fruit:0xfd7e7c8c>

ruby> f1.set_kind("peach")  # 使用該寫入器
   "peach"

ruby> f1.get_kind           # 使用該閱讀器
   "peach"

ruby> f1                    # 檢驗該物件
   #<Fruit:0xfd7e7c8c @kind="peach">

很簡單吧,我們可以儲存取回想查看的水果資料, 但方法名稱有點冗長。以下例子就比較精簡方便:

ruby> class Fruit
    |   def kind=(k)
    |     @kind = k
    |   end
    |   def kind
    |     @kind
    |   end
    | end
   nil

ruby> f2 = Fruit.new
   #<Fruit:0xfd7e7c8c>

ruby> f2.kind = "banana"
   "banana"

ruby> f2.kind
   "banana"

inspect 方法

先離題一下, 現在你會注意到,我們要直接查看物件時,就會出現 #<anObject:0x83678> 這個難懂的訊息。這只是個預設的行為,我們可以隨意變更。只要加上稱為inspect 的方法, 就會傳回以合理方式描述物件的字串,包括物件部分或所有實例變數的狀態。

ruby>class Fruit
    |   def inspect
    |     "a fruit of the #{@kind} variety"
    |   end
    | end
   nil

ruby> f2
   "a fruit of the banana variety"

一個相關的方法稱為 to_s (轉換為字串),於輸出物件時使用。一般來說,你可以將inspect 想像為編寫程式並用以除錯的工具,而to_s 則是重新定義程式輸出的方式。eval.rb 顯示結果時就會使用inspect。你可使用p 方法,輕易地從程式取出除錯輸出。

# 這兩行是相等的:
p anObject
puts anObject.inspect

簡單使用存取器

因為不少實例變數都需要存取器方法,因此 Ruby 提供了一些快捷的方式。

快捷方式 效果 attr_reader :v def v; @v; end attr_writer :v def v=(value); @v=value; end attr_accessor :v attr_reader :v; attr_writer :v attr_accessor :v, :w attr_accessor :v; attr_accessor :w

讓我們善用這些方式加到程式裡吧。首先我們需要一個自動產生出來的閱讀器及寫入器,然後加入新的資訊至 inspect

ruby> class Fruit
    |   attr_accessor :condition
    |   def inspect
    |     "a #{@condition} #{@kind}"
    |   end
    | end
   nil

ruby> f2.condition = "ripe"
   "ripe"

ruby> f2
   "a ripe banana"

更多水果的樂趣

如果沒有人吃成熟的水果,那就讓時間來解決吧。

ruby> class Fruit
    |   def time_passes
    |     @condition = "rotting"
    |   end
    | end
   nil

ruby> f2
   "a ripe banana"

ruby> f2.time_passes
   "rotting"

ruby> f2
   "a rotting banana"

開始前,我們先要說明一個問題。如果我們現在創造第三件水果,那會怎麼樣呢?要記住,指派值予實例變數後,實例變數才會存在。

ruby> f3 = Fruit.new
ERR: failed to convert nil into String

這是因為 inspect 方法發出問題,而且問題很明顯。我們要求它回報水果的種類及狀態,但是f3 還未獲指派任何屬性。如果我們想的話,可以重新編寫inspect 方法,讓它可以用 defined?方法測試實例變數,並只在實例變數存在時才回報,但這樣就可能不是很實用,因為每種水果都有他們的種類與狀態,我們就要確保它們都已經定義。這將在下一節中討論。

0 0
原创粉丝点击