В функции верхнего уровня (все еще метод на самом деле) вы находитесь в немного странном месте: глобальное «основное» пространство (смотрите подсказку, когда вы запускаете irb
, или попробуйте посмотреть на self
внутри такой функции), но также эти функции определены как частные методы внутри класса Object
.
$ 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)
$
Вы можете обойти это, явно объявив эти методы public
, но я не уверен, что мне это нравится! Любопытно, что если вы определяете метод верхнего уровня внутри irb
, то вы можете вызывать его через метод класса Object#foo
, не объявляя его открытым.
Так что это своего рода «подразумеваемое основное пространство имен, взломанное на Object
(но тссс никому не говори)». @foo
определенный внутри функции верхнего уровня, доступен внутри объекта как простой старый атрибут. Вроде, как бы, что-то вроде. Если ваш метод верхнего уровня установлен @foo
, и вы вызываете его без определения области видимости, тогда он объявляется в собственном пространстве имен main
, но если вы вызываете метод класса через Object
, тогда @foo
появляется в пространстве Object
.
Другой пример:
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
1024 * дает *
"foo" # @foo set in main
nil # @foo nil in Object
"foo" # @foo in Object
Обратное также применимо.