4

I'm a bit stumped. Take a look at the add_one method below. When using the increment += operator Ruby throws a NoMethodError. The verbose version works fine.

private method `count=' called for #<Counter:0x007f91a480eb88 @count=0> (NoMethodError)

Why is this?

class Counter
  attr_reader :count

  def initialize
    @count = 0
  end

  def increment
    add_one
  end

private

  attr_writer :count

  def add_one
    self.count += 1          # this causes a error
    # self.count = count + 1 # this works
  end
end

c = Counter.new
puts c.count
puts c.increment
Mohamad
  • 34,731
  • 32
  • 140
  • 219
  • Private methods in ruby cannot be called with an explicit receiver, which is `self`. – avl Nov 26 '14 at 12:49
  • @avlazarov so I'm confused. Is this a bug, or a problem with my code? – Mohamad Nov 26 '14 at 12:59
  • 2
    @avlazarov: Yes, they can, if they are setters. – Jörg W Mittag Nov 26 '14 at 13:36
  • 2
    @Mohamad: This is an oversight in the Ruby Language Specification. I reported this 6 months ago, and it seems that it will be fixed in Ruby 2.2. It might already be fixed in current versions of Ruby 2.1, I'm not entirely sure. See here: https://bugs.ruby-lang.org/issues/9907 – Jörg W Mittag Nov 26 '14 at 13:37
  • 2
    @MarekLipka: Yeah, it's a change in the Ruby Language Specification, they'll probably wait for at least 2.2 if not 2.3 or even 3.0 to make that change. As you can see from the discussion on my bug report, there isn't even agreement about what the spec change should be, exactly. Plus, I have since realized that there are even more cases of methods which are impossible to call if they are `private` because they *require* an explicit receiver, such as `+`, `+@`, `[]` and friends. I believe the entire definition of `private` needs a complete overhaul in the spec. – Jörg W Mittag Nov 26 '14 at 13:52

0 Answers0