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?

nfm
  • 19,689
  • 15
  • 60
  • 90
  • See: http://stackoverflow.com/questions/4312801/is-there-any-benefit-to-using-getters-setters-inside-a-class-for-its-own-fields and http://stackoverflow.com/questions/2884715/what-are-the-benefits-of-using-properties-internally – Josh Lee Jan 18 '11 at 05:00
  • See also: http://stackoverflow.com/questions/1095034/is-it-in-an-anti-pattern-to-always-use-get-and-set-methods-to-access-a-classs-ow – Josh Lee Jan 18 '11 at 05:09

3 Answers3

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.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • So the local variable `color` has scope precedence over the method `color`? – nfm Jan 18 '11 at 05:16
  • 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. – Ed S. Jan 18 '11 at 05:19
  • 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 S. Jan 18 '11 at 05:23
  • @Ed I meant the opposite. I rephrased it a bit. – Josh Lee Jan 18 '11 at 05:29
  • Ah, now that makes more sense ;). +1 – Ed S. Jan 18 '11 at 06:11
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.

Bob.
  • 1,737
  • 1
  • 15
  • 20
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
intellidiot
  • 11,108
  • 4
  • 34
  • 41