1

Consider the following code:

class Dog
  attr_accessor :name, :color

  def initialize(name, color)
  end
end

Within a Ruby object, is the convention to access the instance variable directly (ie @name = name) or to use the setter/getter methods (ie name = name)?

The former is more clear to me, but if you implement your own setter/getter methods (eg to increment a class variable at the same time) then you end up having to use both approaches (ie @name = name ; color = color).

What's the convention within the Ruby community? How should I write my code to make it clear to others who will read it?

2

3 Answers 3

6

Using name = value is an error, because that creates a local variable named name. You must use self.name = value.

As for convention, you can only get away with using @name if you can guarantee that the accessors will always be lightweight attr_accessors. In all other cases, using @name over self.name will violate encapsulation and give yourself a headache. You gave the exact reason in your question — if there is extra logic in the getter/setter, you must duplicate it if you access the instance variable directly.

Sign up to request clarification or add additional context in comments.

5 Comments

So the local variable color has scope precedence over the method color?
Yes, that one will bite you in the ass for sure. Every so often I forget the @ sign and spend five minutes wondering what could have gone wrong.
I'm curious; why do you claim that using self.property_name breaks encapsulation? If there is logic in the setter I would much prefer to use it rather than duplicating code all over the place.
@Ed I meant the opposite. I rephrased it a bit.
Ah, now that makes more sense ;). +1
1

It would be @name. It's more than just a convention. The @ sign defines the scope of the variable to within an instance of the object of which it's defined.

Comments

1

What you have done is the most conventional way, I believe.

Actually attr_accessor creates two instance methods for read and write. It creates 2 methods like:

def color() #getter
  @color
end

and

def color=(color) #setter
  @color = color
end

And something like color = color wont work, because then color will be treated as a local variable if it's found on the left of an assignment. You can use self.color = color though. Again, if the color is not in the left side of any expression, it'll work fine just like the following:

def show_color
  puts color
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.