Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are setter methods not used in initialization?

Tags:

oop

ruby

Recently I've been reading "Practical Object Oriented Design in Ruby", and I noticed one of the best practices was to use accessor methods instead of directly grabbing the @instance_variable. For example:

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    @bar = my_argument
  end

  # bad
  # def lorem_ipsum
  #     @bar * 999
  # end

  # good
  def lorem_ipsum
    bar * 999
  end

end

It makes sense to keep things DRY, and, in case I need to process @bar somehow before actually grabbing its value. However, I noticed that the initialize method sets the value of the @bar instance variable directly:

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    @bar = my_argument #<-- why isn't self.bar = my_argument used here?
  end

Is there a reason for this? Shouldn't the setter method be used instead of directly using the = operator to set the value of the instance variable?

like image 836
bigpotato Avatar asked Dec 12 '13 15:12

bigpotato


3 Answers

You're right, it would make much more sense to do

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    self.bar = my_argument
  end
end

Arguments differ as to whether you should respect encapsulation within the object itself or not, but if you believe in that, then, yes, you should do this.

like image 128
Jörg W Mittag Avatar answered Nov 23 '22 16:11

Jörg W Mittag


The initializer SETS the value upon initialization. The accessor lets you access (read/write) via the symbol after the object is already instantiated.

This post might help you understand: What is attr_accessor in Ruby?

like image 36
Justus Eapen Avatar answered Nov 23 '22 16:11

Justus Eapen


Actually, the setter can be used in initialize the same as in other methods, but setter cannot be used without a receiver.

I think you can use a_foo.bar= or self.bar=, but cannot use bar= without a receiver, because, in the later case, bar will be treated as a local variable rather than a setter method:

class Song
  attr_accessor :name
  def initialize(name)
    self.name = name
  end
  def test_setter1(value)
    @name = value
  end
  def test_setter2(value)
    name = value #name is local variable
  end
end

s = Song.new("Mike")
p s
s.test_setter1("John")
p s
s.test_setter2("Rosy")
p s

This results in:

#<Song:0x23a50b8 @name="Mike">
#<Song:0x23a50b8 @name="John">
#<Song:0x23a50b8 @name="John">
like image 42
uncutstone Avatar answered Nov 23 '22 16:11

uncutstone