2012-01-20 46 views
1

我是Ruby的新手,並且正在使用「Programming Ruby 1.9」(PickAxe)來學習它。在該書中,我看到一個程序,其餘改性從而:在attr_accessor期間輸入鑄造值

1 #!/usr/bin/env ruby -w 
2 
3 class BookInStock 
4   attr_reader :isbn 
5   attr_accessor :price 
6   def initialize(isbn, price) 
7     @isbn = isbn 
8     @price = Float(price) 
9   end 
10 #  def price=(price) 
11 #    @price = Float(price) 
12 #  end 
13 end 
14 
15 b1 = BookInStock.new("isbn1", 3) 
16 p b1 
17 b2 = BookInStock.new("isbn2", 3.14) 
18 p b2 
19 b3 = BookInStock.new("isbn3", "5.67") 
20 p b3 
21 b3.price = "10.32" 
22 p b3 

行號8確保了正確的值被分配給b3.price

但是,如何在不使用第10-12行中的方法的情況下處理像第21行那樣的情況?

有什麼方法可以修改attr_accessor嗎?或者我要求太多:D

我在網上找不到任何這樣的參考文獻。

+0

你不應該存放在'Float's價格。 '0.30 + 0.30 + 0.30'產生'0.8999999999999999'。 –

+0

如果你需要做財務計算,然後使用[BigDecimal](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/bigdecimal/rdoc/BigDecimal.html),而不是'Float' –

+0

謝謝。請參閱其他參考資料。只是這是一個微不足道的例子。再次感謝您的建議。 –

回答

2

attr_accessor :sym是定義簡單的getter和setter方法的類的方法。

您可以定義自己的casting_attr_accessor

class Class 

def casting_attr_accessor(accessor, type) 

    define_method(accessor) do 
     instance_variable_get("@#{accessor}") 
    end   

    define_method("#{accessor}=") do |val| 
     instance_variable_set("@#{accessor}", Kernel.send(type.to_s, val)) 
    end 
end 
end 

,然後在課堂上使用它像

casting_attr_accessor :price, Float 
1

如果不編寫自己的setter方法,則無法做到這一點。什麼attr_accessor :method內部不只是爲你生成一個最簡單的setter方法:

def method=(val) 
    @method = val 
end 

你需要編寫更先進的setter方法手動(在您的情況制定者將包含字符串到浮充轉換)。

1

是的,你問的太多了。您必須完全按照在註釋掉的代碼中定義price=

attr_accessor只是一種簡化的方式來定義

def price=(val) 
    @price = val 
end 

(無型轉換)加上getter方法。

很明顯,當你定義price=時,不再需要attr_accessor :price(只有attr_reader)。

最後,我寧願寫val.to_f而不是Float(val)

+0

'attr_accessor'不是*語法糖,它只是一個枯燥的普通舊消息發送。 –

+0

@JörgWMittag:你說得對。謝謝。 –