0

Specifically, why does the following code output nil instead of 1?

class Foo
  class << self
    @bar = 1
    def bar
      @bar
    end
  end
end
p Foo.bar
3
  • possible duplicate of Ruby metaprogramming: Initialize singleton_class variable Commented Aug 18, 2014 at 21:07
  • Instance variables being nil seems fairly intuitive to me, considering you do not create an instance of Foo. Using class variables (i.e., @@bar) it works fine. Well, never mind. In a normal class the instance variable can indeed be set like you more or less try in the Eigenclass: class A;@a=1;def self.a;@a;end;end;p A.a This would print 1 just fine, without creating an instance of A. Commented Aug 18, 2014 at 21:07
  • ya, it's a dupe, I just didn't see the original when I searched, thanks! the title is not intuitive... Commented Aug 18, 2014 at 21:17

3 Answers 3

1

In the << self block, self is an instance of #<Class:Foo>.

class Foo
  puts "self in Foo declaration is: #{self} #{self.class} #{self.object_id}"
  class << self 
    @bar = 1
    puts "self in Foo.self declaration is: #{self} #{self.class} #{self.object_id}"
    def bar
      puts "self in class method is #{self} #{self.class} #{self.object_id}"
      @bar
    end
  end
end
p Foo.bar

This code outputs:

self in Foo declaration is: Foo Class 69910818825400
self in Foo.self declaration is: #<Class:Foo> Class 69910818825380
self in class method is Foo Class 69910818825400

So a slight modification to your code, that works as expected, is:

class Foo @bar = 1 class << self def bar @bar end end end p Foo.bar

Sign up to request clarification or add additional context in comments.

Comments

0

Even though you're modifying the Class definition of Foo with self you are still setting an instance variable which is not available through class scope.

If you want to have a class variable do it like.

class Foo
  class << self
    @@bar = 1
    def bar
     @@bar
    end
  end
end
p Foo.bar # 1

Comments

0

This is in no way different from:

class Foo
  @bar = 1

  def bar; @bar end
end

Instance variables belong to objects and are always looked up on self. bar is an instance method, so the @bar inside bar belongs to some instance of Foo (self is the receiver of bar at that point). The @bar at the beginning belongs to the class itself (self is Foo at that point).

Those are simply two completely different objects. The two ´@bar`s are completely unrelated.

In your example: the first @bar belongs to the singleton class of Foo, the second @bar belongs to the instance of the singleton class of Foo (i.e. Foo).

Here's how you could make it work:

class Foo
  @bar = 1

  def self.bar; @bar end
end

Comments

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.