Kostas Andrianos
Kostas Andrianos

Reputation: 1619

Instance variable changes without explicitly telling it to

This is a very weird one.

So I have a class LibSystem

class LibSystem
  attr_accessor :borrower
  attr_reader :books
  def initialize(book_inventory = [])
    @borrower = []
    @books = book_inventory
    @borrowed = []
  end
#...
end

From another file I do require_relative and the file which contains it. Then I do this...

#...
sys = LibSystem.new(books)
puts sys.books.length
books << Book.new("Adventure Of My New Cat", "3-598-21515-0", "3", "funny publications", "2001", [auth3], 1)
puts sys.books.length

What I expect is for the first length to be 9 (size of the array I passed to the constructor) and the second to be the same. Instead I get 9 and 10 accordingly. This seems like the instance variable inside my sys object is updating along with the array that was passed into it. This seems completely wrong to me. Am I doing anything wrong here, or is this the standard behavior? Thank you.

The title is probably inaccurate, if you have anything better, feel free to edit.

Upvotes: 0

Views: 51

Answers (1)

mattbornski
mattbornski

Reputation: 12563

Arrays and hashes in Ruby are by default not copied. Inside LibSystem you assign the passed book_inventory to the @books instance variable; Your new LibSystem instance just holds on the address of the existing array without copying the contents. When you used << to append to the array, you modified the same array.

It is sometimes considered a good practice to copy the arrays or dictionaries used in an initializer to avoid exactly this kind of interference, although your use case may vary.

Upvotes: 1

Related Questions