In a top-level function (still a method really), you're in a slightly strange place: a global "main" space (see the prompt when you run irb
, or try looking at self
inside such a function), but also these functions are defined as private methods inside the Object
class.
$ cat foo
def foo
p self
p self.class
puts 'foo'
end
foo
Object.foo
$ ruby foo
main
Object
foo
foo:8: private method `foo' called for Object:Class (NoMethodError)
$
You can sneak around this by explicitly declaring these methods public
, but I'm not sure I like this! Curiously, if you define a top-level method inside irb
, then you can call it via the class method Object#foo
without declaring it public.
So this is a kind of an "implied main namespace hacked onto Object
(but shhh don't tell anyone)". @foo
defined inside a top-level function is available inside Object, as a plain old attribute. Sort of. If your top-level method set @foo
and you call it without scoping then it is declared in the eigen-like main
namespace, but if you call the class method via Object
then @foo
appears in the space of Object
.
Another example:
public
def set_foo
@foo = 'foo'
end
def get_foo
@foo
end
def Object.get_foo_again
@foo
end
set_foo
p get_foo
p Object.get_foo_again
Object.set_foo
p Object.get_foo_again
gives
"foo" # @foo set in main
nil # @foo nil in Object
"foo" # @foo in Object
The converse also applies.