Ruby attr_reader allows you to change a string variable if you use <<

In some strange behavior, and wonders if anyone else can confirm what I see.

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 be changing the value of @val, although I only granted it read privileges.

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

It returns

hello
hello world

This is just the result of some testing that I did in irb, so I'm not sure if this is always the case.

+5
source share
4 answers

You are not actually writing the val attribute. You read it and call the method on it (method "<").

, , , , @val attr_reader.

+4

:

test = TestClass.new([])

( puts p, ):

[]
['hello']

. "val", - . - , - .

- ( ), - ( ).

, freeze:

class TestClass
  attr_reader :val

  def initialize(value)
   @val = value
   @val.freeze
  end
end

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

:

__temp.rb:12:in `<main>': can't modify frozen string (RuntimeError)
hello
+2

, .

test.val = "hello world"

- @val ( ),

test.val << " world"

, @val.

Ruby ? - , , .

+2

, . .

attr_reader attr_writer "getter" "setter" .

Without the getter method, you do not have access to instance variables of an object, simply because you are not in the context of this object. The setter method is essentially as follows:

def variable=(value)
  @variable = value
end

Since the instance variable points to a mutable object with the set of methods itself, if you "get" it and manipulate it, then it is reasonable that these changes be accepted. You do not need to use the setter method above to call variable.<<(value).

0
source

All Articles