Какую область видит символ "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
Другие вопросы по тегам