Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby attr_reader allows one to modify string variable if using <<

Ran into some weird behaviour and wondering if anyone else can confirm what I am seeing.

Suppose you create a class with a member variable, and allow it to be read with attr_reader.

class TestClass
  attr_reader :val

  def initialize(value)
   @val = value
  end
end

Now when I do the following, it seems to modify the value of @val, even though I have only granted it read privileges.

test = TestClass.new('hello')
puts test.val
test.val << ' world'
puts test.val

This returns

hello
hello world

This is just the result from some testing I did in irb so not sure if this is always the case

like image 693
Robin Avatar asked Nov 03 '11 21:11

Robin


2 Answers

You are not really writing the val attribute. You are reading it and invoking a method on it (the '<<' method).

If you want an accessor that prevents the kind of modification you describe then you might want to implement a method that returns a copy of @val instead of using attr_reader.

like image 141
Steve Avatar answered Sep 20 '22 12:09

Steve


Assigning is different to modifying, and variables are different to objects.

test.val = "hello world"

would be a case of assignment to the @val instance variable (which would not work), whereas

test.val << " world"

would be a modification of the object referred to by @val.

Why does the absence of the assignment operator permit me to modify a Ruby constant with no compiler warning? is a similar question, but talking about constants rather than instance variables.

like image 24
Andrew Grimm Avatar answered Sep 19 '22 12:09

Andrew Grimm