Какую область видит символ "at" (@) в функциях Ruby?
Прошло много времени с тех пор, как я в последний раз занимался программированием на Ruby - глядя на чужой код, я вижу @
сигил в функции (ане метод - внешний по отношению к определению любого класса), который, как я понял, относится к членам экземпляра.
Является ли модуль подразумеваемым self
в функции?
4 ответа
В функции верхнего уровня (все еще метод на самом деле) вы находитесь в немного странном месте: глобальное "основное" пространство (смотрите подсказку при запуске 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
дает
"foo" # @foo set in main
nil # @foo nil in Object
"foo" # @foo in Object
Обратное также применимо.
Предположение, что это "функция, а не метод", неверно. Весь код Ruby происходит в контексте какого-либо объекта. "Глобальный" контекст - это объект, называемый main
(пытаться ruby -e "puts self"
если не веришь). Методы, определенные в верхней области видимости, становятся методами экземпляра Object. Это означает, что метод будет доступен где угодно, с self
(и, следовательно, контекст, к которому относятся переменные экземпляра) в зависимости от того, где вызывается метод
@ делает переменную переменной экземпляра. Похоже, он не является частью явно объявленного класса, поэтому он будет доступен в основном объекте, как указал Чак. Это проще проиллюстрировать на примере:
$ irb
irb(main):001:0> @var = 1
=> 1
irb(main):002:0> class New
irb(main):003:1> def test
irb(main):004:2> puts @var
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> test = New.new
=> #<New:0xb7ccbc14>
irb(main):008:0> test.test
nil
=> nil
irb(main):009:0> def test2
irb(main):010:1> puts @var
irb(main):011:1> end
=> nil
irb(main):012:0> test2
1
=> nil