2014-11-16 26 views
2
class Book 
    attr_accessor :author 
    attr_reader :title 
    attr_reader :comments 
    def initialize(author, title) 
    @author = author 
    @title = title 
    @comments = [] 
    end 
end 

book = Book.new("Chuck Palahniuk", "Fight Club") 


book.comments << "#{book.title} was a good book" 
book.comments.each do |p| 
    puts p 
end 
# Fight Club was a good book 

如果comments方法只是一個attr_reader而不是attr_writer,爲什麼< <追加工作?是因爲它繞過了attr_writer的=號嗎?確實會有<< sign bypass =登入ruby嗎?

回答

2

<<聲明修改數組是book.comments引用,它不會改變book.comments本身。

打印其object_id前後:

puts book.comments.object_id 
book.comments << "#{book.title} was a good book" 
puts book.comments.object_id 

你會看到它的同一個對象。


比較非法聲明:

book.comments = [] 
+1

這是一個準確的解釋。我會補充說,你可以通過調用['freeze']來避免修改數組的內部狀態(即使用'<<'方法)(http://ruby-doc.org/core-2.1.5/Object.html #method-i-freeze)方法就可以了。 –

+0

@GabrieldeOliveira請注意使用_freeze _...,除非您真的需要它.. –

+0

@Arup,請詳細說明。 –

1

雖然你已經創建了book對象,那麼只有實例變量@comments已爲book對象創建的。現在,當您呼叫的writeer方法comments,這是給你的陣列例如回來,你已分配給它,而實例化book。現在Array有方法Array#<<追加新值到數組,這就是當你做book.comments << "#{book.title} was a good book"時發生的事情。

book.comments << "#{book.title} was a good book" 
# means 
[] << "#{book.title} was a good book" 
# [] has been returned by book.comments 
相關問題