Trying to learn / understand Ruby setter and gette

2019-01-03 02:53发布

问题:

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.

回答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.



回答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.



回答3:

Surely they both return a value, but their behavior are different.

Let's say there is already a member @a .

with getter, one obtains the current value of @a, without modifying it.

with setter, one modifies @a, and get its new value as return value.

when thinking about behavior of setter, note:

  1. the old value of @a can not be obtained with setter, and got overwritten.

  2. what returned by setter, is actually already known before invoking setter.



回答4:

May be the attention for getters and setters is because some other languages allow you to access class variables directly. Python:

class k:
    i = 100

print k.i # 100
k.i = 200
print k.i # 200

In contrast, Ruby keeps all of its variables completely private to the class and only exposes them through accessor methods.

In your example, if you remove the getter, you can indeed interact with the variable (that is: change it) trough the setter, but you can't get it back (in a regular way) when you need it.



标签: