Ruby 如何从类def之外定义的数组生成一些方法

Ruby 如何从类def之外定义的数组生成一些方法,ruby,metaprogramming,Ruby,Metaprogramming,这不是,但这是我需要的: 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 - Obj

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

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”]
类MyAwesomeClass
变量_of _doom.each do | name|
定义_方法(“#{name}”)do
点名
结束
结束
结束
放置(MyAwesomeClass.instance\u methods-Object.instance\u methods)。检查
#=>NameError:MyAwesomeClass:Class的未定义局部变量或方法“variable\u of\u doom”
#=>第9行无标题4中的方法
#=>第7行无标题4中的方法

在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
# => 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

在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
# => 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

如何解决这个问题已经在另一个答案中给出。我建议您执行以下
指令
,以检查范围规则:

$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]

如何解决这个问题已经在另一个答案中给出。我建议您执行以下
指令
,以检查范围规则:

$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]

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

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
厄运的变量是常数吗?如果是这样的话,下面的方法会起作用,因为类可以访问在其自己的类定义之外声明的常量:

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

我不会求助于使
$variables\u of_doom
成为一个全局变量。这是不必要的,原则上应该避免。

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

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
厄运的变量是常数吗?如果是这样的话,下面的方法会起作用,因为类可以访问在其自己的类定义之外声明的常量:

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

我不会求助于使
$variables\u of_doom
成为一个全局变量。在Ruby中,一个
(或
定义
)块划分了一个新的、独立的作用域,在这个作用域中,无法访问周围作用域中的局部变量。如果需要将周围的局部变量包含在范围内,可以使用块来解决此问题,如:

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

在Practical Bookshelf的Ruby元编程中,他们将这种技术的使用描述为“作用域门”:当你想为局部变量创建一个新的作用域时使用
class
def
块,当你不想创建一个新的作用域时使用块。

在Ruby中,一个
class
(或
def
)块划分一个新的,无法访问周围范围中的局部变量的单独范围。如果需要将周围的局部变量包含在范围内,可以使用块来解决此问题,如:

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

在Practical Bookshelf的Ruby元编程中,他们将这种技术的使用描述为“作用域门”:当你想为局部变量创建一个新的作用域时,使用
class
def
块,当你不想创建时,使用块。

相反,创建glabal变量不是一个好主意,将变量_of _doom移动到类范围内将是一个好主意。

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

我知道的不多,但我知道人们确实对全局变量很失望。在我的例子中,它可能工作得很好,因为这段代码不太可能与其他人的东西发生冲突。话虽如此,结尾的那条线却是纯金的。“puts(MyAwesomeClass.instance\u methods-Object.instance\u methods).inspect”@John,像这样的全局变量确实很糟糕,但你似乎想使用一个,但不明白它为什么不起作用,所以我解释了如何使它起作用。我不知道你为什么不喜欢在
MyAwesomeClass
中包含
variable\u of_doom
,所以我没有提出更好的替代方案,尽管我怀疑在类中将其设为常量会更好。我知道的不多,但我知道人们确实对全局变量很反感。在我的例子中,它可能工作得很好,因为这段代码不太可能与其他人的东西发生冲突。话虽如此,结尾的那条线却是纯金的。“puts(MyAwesomeClass.instance\u methods-Object.instance\u methods).inspect”@John,像这样的全局变量确实很糟糕,但你似乎想使用一个,但不明白它为什么不起作用,所以我解释了如何使它起作用。我不知道你为什么不喜欢在
MyAwesomeClass
中加入
variable\u of_doom
,所以我没有提出更好的选择,尽管我怀疑在类内将其设置为常量会更好。+1的彻底性和幽默性。我无法让它为我工作,但我怀疑没有人是罪魁祸首。亚历克斯·D的回答起了关键作用。由于其彻底性和幽默性+1。我无法让它为我工作,但我怀疑没有人是罪魁祸首。亚历克斯的回答起了作用。