Trying to learn / understand Ruby setter and getter methods

I'm just learning to program and have decided to try Ruby. I'm sure this is a stupid question, but the instructor is talking about setter and getter methods, and I'm confused. Here is the example:

class Human
  def noise=(noise)
    @noise = noise
  end

  def noise
    @noise
  end
end

From this, the class is instantiated, and I can puts this out:

man = Human.new
man.noise=("Howdie!")
puts man.noise

This results in Howdie!

Now what confuses me is that the instructor is saying without the getter method (the 2nd of the two methods), there is no way to interact with the instance variable @noise.

But when I remove the getter method, I'm able to still access @noise, see example:

class Human
  def noise=(noise)
    @noise = noise
  end
end

man = Human.new
puts man.noise=("Howdie!")

This works the same as when the getter method it used.

So now I'm confused. Why is the getter needed? What does the instructor mean by not being able to access the instance variable without it? Is it possible he's using an older version of Ruby?

Thanks in advance for your help.


Solution 1:

You can interact with that instance variable from other methods belonging to that instance, even if there is no getter:

def noise=(noise)
  @noise = noise
end

def last_noise
  @noise
end

There doesn't need to be a getter defined with the same name as the method; the two are not linked at all. The getter is needed to "get" the value of the instance variable, but only in a short syntax.

What's happening in your example is that you're initializing a new object (Human.new), and then using a method (noise=, yes the method name contains the = symbol) that just-so-happens to define an instance variable (that is, a variable just for that instance), and then finally retrieving that instance variable with another method call.

You can actually use instance_variable_get to get the instance variable without defining any getter at all:

man = Human.new
man.noise = "Howdie"
man.instance_variable_get("@noise")

This will return "Howdie", even though there is no getter defined.

And no, I don't think he's using an older version of Ruby.

Solution 2:

The line of code

puts man.noise=("Howdie!")

does NOT use the getter method, so the getter method does not need to be defined for it to work. That line just uses the setter method. The return value of the setter method is automatically equal to whatever is on the right-hand side of the equal sign, so "Howdie!" gets passed to puts.

The line of code

puts man.noise

DOES use the getter method, and it would not work if you remove the getter method.