4

I've been playing around with Ruby mostly in the top level and I typically write code like:

@x = 'foo'
def show_var
  puts @x
end

show_var # => foo

I thought that instance variables were available to both the Class and the Object, based off how this example works.

Today I ran into this, and it looks like my understanding of instance variables is incorrect:

class Test
  @x = "foo" #you would need to define this inside 'initialize' for this to be available to show_var
  def show_var
    puts @x
  end 
end

Test.new.show_var # => nil

It looks like the second example is how instance variables work. If you define an instance variable inside the Class, then it only exists inside that scope, and does not exist for instance methods.

Then my question is... why does the first case output 'foo' when the variable @x shouldn't exist inside the scope of an instance method? Also, what is the proper way for defining variables in the top-level Class that you want to use for your top-level methods?

2
  • 1
    In addition to the answers already, try Test.instance_variable_get(:@x) - the instance variable @x has been defined on the Test class (which is an object of type Class) - it can take a while to realise what that means, but it's a key part of Ruby to understand this Commented Jul 27, 2013 at 20:01
  • In your last example, you've create what's called a class instance variable. They are preferred over class variables (@@). Commented Jul 27, 2013 at 20:52

2 Answers 2

5

The method in the first example is at the top level. Which means it belongs to a special top level object main. You can't really create more copies of main, so self inside and outside of that method is the same. Check this out:

self # => main
def show_var
  self # => main
end

class Test
  self # => Test
  def show_var
    self # => #<Test:0x007fdf9c892d70>
  end 
end
Sign up to request clarification or add additional context in comments.

Comments

1

Look below:

@x = 'foo'
def show_var
  puts @x,self
  p defined? @x
end

show_var
# >> foo
# >> main
# >> "instance-variable"

In the first case you defined @x in the main scope. And then when call the method show_var,from the main,thus you got the output of @x,which is not the case of the other.

class Test
  @x = "foo" 
  def show_var
    p @x,self 
    p defined? @x
  end 
end

Test.new.show_var
# >> nil
# >> #<Test:0x9b6fcd4>
# >> nil

1 Comment

Oh ok, thanks. If I were to do... class Test; @x='foo';def self.show_var; puts @x; end; show_var; end; Test.new Then that's what I'm doing at the top-level, which then outputs 'foo'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.