0
This works:

class MyAwesomeClass

variable_of_doom = ["things", "stuff", "chunky_bacon"]  

  variable_of_doom.each do |name|
    define_method("#{name}") do
      puts name
    end
  end
end

puts (MyAwesomeClass.instance_methods - Object.instance_methods).inspect

# => ["things", "stuff", "chunky_bacon"]

这不是,但这是我需要的:

variable_of_doom = ["things", "stuff", "chunky_bacon"]  

class MyAwesomeClass

  variable_of_doom.each do |name|
    define_method("#{name}") do
      puts name
    end
  end
end

puts (MyAwesomeClass.instance_methods - Object.instance_methods).inspect
# => NameError: undefined local variable or method ‘variable_of_doom’ for MyAwesomeClass:Class

# => method <class:MyAwesomeClass>  in untitled 4 at line 9
# => method <main>  in untitled 4 at line 7
4

5 回答 5

2

你的问题归结为这个失败的例子:

variable_of_doom = %w(famine plague flood war pestilence drought television)

class MyAwesomeClass
  # undefined local variable or method `variable_of_doom' for MyAwesomeClass:Class
  puts variable_of_doom
end

厄运的变量是不变的吗?如果是这样,则以下方法有效,因为类可以访问在其自己的类定义之外声明的常量:

VARIABLE_OF_DOOM = %w(famine plague flood war pestilence drought dos)

class MyAwesomeClass
  puts VARIABLE_OF_DOOM
end

如果您需要动态变量,您可以使用知道如何传递它们的方法创建一个模块或类。

module VarsOfDoom
  VOD = %w(famine plague flood war pestilence drought computer-mouse)

  def self.dynamic
    VOD.shuffle
  end
end

class MyAwesomeClass
  # Works because the module VarsOfDoom is itself a constant.
  puts VarsOfDoom::VOD
  puts
  puts VarsOfDoom.dynamic
end

我不会诉诸于制作$variables_of_doom一个全球性的。没有必要,原则上应该避免。

于 2013-06-22T14:23:19.873 回答
1

在 Ruby 中,class(或def)块划分了一个新的、单独的范围,在该范围内,来自周围范围的局部变量是不可访问的。如果您需要周围的局部变量在范围内,您可以使用块来解决这个问题,例如:

 variable_of_doom = ["things", "stuff", "chunky_bacon"]

 MyAwesomeClass.class_eval do
   variable_of_doom.each do |var|
     # do whatever you need here
   end
 end

在 Pragmatic Bookshelf 的Ruby Metaprogramming中,他们将这种技术的使用描述为“范围门”:当您想为局部变量创建新范围时使用classordef块,当您不想时使用块。

于 2013-06-22T15:23:58.073 回答
0

如何解决该问题已在其他答案中说明。我想建议您执行instropection以下操作来检查范围规则:

variable_of_doom = ["things", "stuff", "chunky_bacon"] 

defined? variable_of_doom # => "local-variable"
local_variables.include? :variable_of_doom # => true

class MyAwesomeClass
  p defined?(variable_of_doom)
  p local_variables.include?(:variable_of_doom )
end
# >> nil
# >> false
于 2013-06-22T14:22:14.663 回答
0

制作 glabal 变量不是一个好主意,相反,将 variable_of_doom 移动到 Class 范围内将是一个好主意。

于 2013-06-24T08:38:30.160 回答
0

在 Ruby 中,全局变量需要用 表示,$就像实例变量用 表示一样@。所以这有效:

$variable_of_doom = ["things", "stuff", "chunky_bacon"] 
class MyAwesomeClass

  $variable_of_doom.each do |name|
    define_method("#{name}") do
      puts name
    end
  end
end

puts (MyAwesomeClass.instance_methods - Object.instance_methods).inspect
# => [:things, :stuff, :chunky_bacon]
于 2013-06-22T14:14:31.080 回答