2016-01-22 3 views
5

я заметил следующий код синтаксически корректен:Локальные переменные класса в рубин

class Foo 
    bar = 3 
end 

Теперь я знаю, что переменные экземпляра доступ @ и класса переменных по @@, но я не мог выяснить, где bar хранится в этом случае или как получить к нему доступ.

Как я могу найти область bar?

+2

Это локальная переменная так же, как и любой другой локальной переменной. –

ответ

7

Тело класса в Ruby является исполняемым только рубиновым кодом. Это действительно локальные переменные (нет необходимости в котировке) и следуют правилам «regular», являющимися локальными переменными. Вы можете получить доступ к ним в теле класса. Если вы хотите буквально сферу, где bar определен, вы можете использовать Kernel.binding:

class Foo 
    bar = 42 

    @@scope = binding 

    def self.scope 
    @@scope 
    end 
end 

Foo.scope.local_variables   # => [:bar] 
Foo.scope.local_variable_get(:bar) # => 42 

вещь отметить - использование def изменяет масштаб, таким образом, они не будут видны внутри методы, определенные с помощью def.

2

Переменная будет доступна до тех пор, пока вы не закроете определение класса. Он не будет доступен внутри методов, которые вы определяете.

Вы можете попробовать запустить код в IRB:

$ irb 
irb(main):001:0> class Test 
irb(main):002:1> bar = 1 
irb(main):003:1> puts bar 
irb(main):004:1> end 
1 
=> nil 
irb(main):005:0> puts bar 
NameError: undefined local variable or method `bar' for main:Object 
     from (irb):5 
     from /usr/bin/irb:11:in `<main>' 
irb(main):006:0> class Test 
irb(main):007:1> puts bar 
irb(main):008:1> end 
NameError: undefined local variable or method `bar' for Test:Class 
     from (irb):7:in `<class:Test>' 
     from (irb):6 
     from /usr/bin/irb:11:in `<main>' 
irb(main):009:0> 

Проверить наличие в методах экземпляра:

irb(main):018:0> class Test 
irb(main):019:1> bar = 1 
irb(main):020:1> def test 
irb(main):021:2> puts bar 
irb(main):022:2> end 
irb(main):023:1> end 
=> :test 
irb(main):024:0> a = Test.new 
=> #<Test:0x00000000f447a0> 
irb(main):025:0> a.test 
NameError: undefined local variable or method `bar' for #<Test:0x00000000f447a0> 
     from (irb):21:in `test' 
     from (irb):25 
     from /usr/bin/irb:11:in `<main>' 

Проверить наличие свободных мест в методах класса:

irb(main):026:0> class Test 
irb(main):027:1> bar = 1 
irb(main):028:1> def self.test 
irb(main):029:2> puts bar 
irb(main):030:2> end 
irb(main):031:1> end 
=> :test 
irb(main):032:0> Test.test 
NameError: undefined local variable or method `bar' for Test:Class 
     from (irb):29:in `test' 
     from (irb):32 
     from /usr/bin/irb:11:in `<main>' 
+0

Есть ли способ «сохранить» эти объявления? Способ распространения их на метод или что-то еще? –

+0

@ GiladNaaman: nope. Отсюда и имя, _local_ variable. :) –

4

Доступно из того же класса.

class Foo 
    bar = 3 
    bar # => 3 
end 

Это лексическая область видимости, так оно доступно внутри блока:

class Foo 
    bar = 3 
    pr = ->{p bar} 
    pr.call # => 3 
end 

, но он не доступен даже в том же классе, как только тело класса было закрыто:

class Foo 
    bar = 3 
end 
class Foo 
    bar # => error 
end 

и не может быть получен из определения метода:

class Foo 
    bar = 3 
    def baz; bar end 
    new.baz # => error 
end 
0

Вы могли бы сделать его постоянным и использовать его методы экземпляра и класса:

class Foo 
    Bar = 3 

    def local_bar(param = Bar) 
     param 
    end 
end 

p Foo.new.local_bar 
#=> 3