kriysna
kriysna

Reputation: 6168

understand self for attr_accessor class method

class Test
  class << self
    attr_accessor :some

    def set_some
      puts self.inspect
      some = 'some_data'
    end
    def get_some
      puts self.inspect
      some
    end
  end
end

Test.set_some => Test
puts Test.get_some.inspect => Test nil

Here above I could find self as Test itself but not returning the some_data as output.

But while I modified in following way it returns expected output

class Test
  class << self
    attr_accessor :some

    def set_some
      puts self.inspect
      self.some = 'some_data'
    end
    def get_some
      puts self.inspect
      self.some
    end
  end
end

Test.set_some => Test
puts Test.get_some.inspect => Test some_data

What is the differences?

EDIT

Now in the first example if I set as get some method as

Test.some = 'new_data'
puts Test.some.inspect #=> new_data
Test.set_some
puts Test.get_some.inspect => new_data

Now it made me much more confused.

Upvotes: 6

Views: 4236

Answers (5)

ewH
ewH

Reputation: 2683

Example 1 with no method override and no local variable

class Foo
  def initialize
    @foo = 'foo'
  end

  def print_foo
    print @foo
    print self.foo
    print foo
  end
end

@foo, self.foo, and foo will access instance variable @foo within the instance method:

Foo.new.print_foo #=> foofoofoo

Example 2 with method override

class Foo
  def initialize
    @foo = 'foo'
  end

  def foo
    return 'bar'
  end

  def print_foo
    print @foo
    print self.foo
    print foo
  end
end

@foo will access the instance variable, but self.foo and foo will call the foo override method:

Foo.new.print_foo #=> foobarbar

Example 3 with method override and local variable

class Foo
  def initialize
    @foo = 'foo'
  end

  def foo
    return 'bar'
  end

  def print_foo
    foo = 'baz'
    print @foo
    print self.foo
    print foo
  end
end

@foo accesses instance variable, self.foo accesses override method, and foo accesses local variable:

Foo.new.print_foo #=> foobarbaz

Upvotes: 0

Orlando
Orlando

Reputation: 9712

in the first method

def set_some
  puts self.inspect
  some = 'some_data'
end

some is a local variable.. its not the same as @some that is a instance variable (in this case a class instance variable) so the value disappears when the method ends.

if you want to call the setter method some or set @some to something then do this

@some = 'some_data'

or

self.some = 'some_data'

in the second method

def get_some
  puts self.inspect
  self.some
end

your calling the method some. which returns the instace variable @some.. and since at this point @some has no value.. returns nil..

Upvotes: 0

Sony Santos
Sony Santos

Reputation: 5545

In the first example some is a local variable.

In the second one, some is a method of self. Why? Because attr_accessor :some is the same as:

def some= (val)
  @some = val
end

def some
  return @some
end

So, you have created the getter and setter methods for the instance variable @some (it's an instance variable of the object Test, as every class is also an object of class Class).

Upvotes: 0

Reactormonk
Reactormonk

Reputation: 21730

some = :foo makes ruby think it should create a new local variable with name some. If you want to call some=(), you have to use an explicit reciever - as in self.some = :foo. I once lost a bet on that... :-/

Upvotes: 12

lzap
lzap

Reputation: 17173

It's (local) variable in the first example

Upvotes: 1

Related Questions