1

I don't understand why I get a nil error. I created the setter properly. But it does not accept -=, +=, or itself behind the = operator. Why?

class Test
  def var; @var || 0; end
  def var=(value)
    @var = value
  end

  def initialize
    @var = 2.4 # Sample value
  end

  def test
    puts var
    var -= 1 # <<< crash: undefined method for nil class
    puts var
    var = var - 1 # <<< crash: undefined method for nil class
    puts var
  end
end

a = Test.new
a.test
Napoleon
  • 1,072
  • 5
  • 17
  • 31

3 Answers3

6

Write as

def test
    puts var
    self.var -= 1
    puts var
    self.var = var - 1
    puts var
end

If you don't use self, then Ruby will treat those var as a local variables, rather then setter method calls.

Just remember, in Ruby method call can never be made without receiver(implicit/explicit). Now if you write var = 1, Ruby will treat as local variable assignment. But if you write self.var, Ruby will parse it as a method call, and will try to call your setter method, if you defined. Also remember self.var = 1 is a syntactic sugar of self.var=(1).

There is more interesting discussion about the same, worth to read Private setters can be called by self, why not getters?

There is a recent bug was found regarding the private setters. Here is the Bug ticket, and it is now fixed too.

Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
  • That indeed seems to be the problem. But why do I have to add self in this case? It's within the same class as a method (not static or anything). – Napoleon May 29 '14 at 18:22
  • So it's only @var or self.var from within the class itself. I'm more used to C# so that's why I'm so confused I guess. Thanks for the quick solution. – Napoleon May 29 '14 at 18:31
  • @Napoleon ofcourse `self.var` if you want to call setter method. – Arup Rakshit May 29 '14 at 18:33
0

Because var is nil. you need to assign some value to it first

def test
    puts var
    var=0 
    var -= 1 # <<< crash: undefined method for nil class
    puts var
    var=0
    var = var - 1 # <<< crash: undefined method for nil class
    puts var
  end
Muhammad Zaighum
  • 560
  • 4
  • 21
-1

UPDATE: It's not clear whether you want an instance variable or a class variable for 'var'. The example below is for an instance variable.

I would use attr_reader, or attr_accessor if you want to do this external to the class.

class Test
   attr_reader :var

   def initialize
      @var=2.4
   end

   def test
     puts @var
     @var -= 1
     puts @var
     @var = @var - 1
     puts @var
   end
end

t=Test.new
t.test
puts t.var

$ /tmp/t.rb
2.4
1.4
0.3999999999999999
0.3999999999999999
Steeve McCauley
  • 683
  • 5
  • 11