Какую область видит символ "at" (@) в функциях Ruby? - PullRequest
1 голос
/ 08 мая 2009

Прошло много времени с тех пор, как я в последний раз занимался программированием на Ruby - глядя на чужой код, я вижу сигилу @ в функции ( не метод - внешний для любого определения класса) я понял, что это относится к членам экземпляра.

Является ли модуль подразумеваемым self в функциях?

Ответы [ 4 ]

3 голосов
/ 08 мая 2009

В функции верхнего уровня (все еще метод на самом деле) вы находитесь в немного странном месте: глобальное «основное» пространство (смотрите подсказку, когда вы запускаете 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

Обратное также применимо.

2 голосов
/ 08 мая 2009

Предположение, что это «функция, а не метод», неверно. Весь код Ruby происходит в контексте какого-либо объекта. «Глобальный» контекст - это Объект с именем main (попробуйте ruby -e "puts self", если вы не верите этому). Методы, определенные в верхней области видимости, становятся методами экземпляра Object. Это означает, что метод будет доступен везде , с self (и, следовательно, контекстом, к которому относятся переменные экземпляра), в зависимости от того, где метод вызывается

1 голос
/ 08 мая 2009

@ делает переменную экземпляром переменной. Похоже, что он не является частью явно объявленного класса, поэтому он будет доступен в основном объекте, как указал Чак. Это проще проиллюстрировать на примере:

$ 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
1 голос
/ 08 мая 2009

Я думаю, что это распространяется на модуль.

...