绕过Ruby';定义类方法时的作用域门

绕过Ruby';定义类方法时的作用域门,ruby,Ruby,我有一个classa,我想匿名扩展它,并向子类添加一个class方法。例如: class A end Class.new A do def self.new_class_method puts 'I am a class method' end end.new_class_method => I am a class method 上述示例运行良好,除非您希望访问def self.new_class_方法块之外的一些变量。E、 g, greeting = 'hello

我有一个class
a
,我想匿名扩展它,并向子类添加一个class方法。例如:

class A
end

Class.new A do
  def self.new_class_method
    puts 'I am a class method'
  end
end.new_class_method

=> I am a class method
上述示例运行良好,除非您希望访问
def self.new_class_方法
块之外的一些变量。E、 g,

greeting = 'hello'

Class.new A do
  def self.new_class_method
    puts greeting + ' I am a class method'
  end
end.new_class_method

=> NameError: undefined local variable or method `greeting'

我使用的是Ruby1.8.7,这是令人伤心的,因为我相信Ruby1.9+包含了一个类似于
define\u方法的类方法。是否有人对1.8.7进行过修改

不确定这是否能解决您的问题,但将问候语改为大写(使其成为常量)会起作用

class A
end

Greeting = 'hello'

Class.new A do
  def self.new_class_method
    puts Greeting + ' I am a class method'
  end
end.new_class_method

不确定这是否能解决您的问题,但将问候语改为大写(使其成为常量)会起作用

class A
end

Greeting = 'hello'

Class.new A do
  def self.new_class_method
    puts Greeting + ' I am a class method'
  end
end.new_class_method

我已经在Ruby 1.8.7中测试了以下内容:-

greeting = 'hello'

class A
end

Class.new A do 
  meta_klass = class << self; self ;end
  meta_klass.send(:define_method, :new_class_method) do
    puts greeting + ' I am a class method'
  end
end.new_class_method
# >> hello I am a class method
greeting='hello'
甲级
终止
新课程
meta_klass=class>您好,我是一个类方法

由于Ruby 1.8.7不支持,我使用了
meta_klass=class我已经在Ruby 1.8.7中测试了以下内容:-

greeting = 'hello'

class A
end

Class.new A do 
  meta_klass = class << self; self ;end
  meta_klass.send(:define_method, :new_class_method) do
    puts greeting + ' I am a class method'
  end
end.new_class_method
# >> hello I am a class method
greeting='hello'
甲级
终止
新课程
meta_klass=class>您好,我是一个类方法
由于Ruby 1.8.7不支持,我更普遍地使用了
meta_klass=class

class A
end

class Object
  def meta_def name, &blk
    (class << self; self; end).instance_eval { define_method name, &blk }
  end
end

greeting = 'hello'

Class.new A do
  meta_def :new_class_method do
    puts greeting + ' I am a class method'
  end
end.new_class_method
  #=> hello I am a class method
A类
终止
类对象
定义元定义名称(&blk)
(类你好,我是一个类方法
如果你觉得这很有用,不要谢我,要谢一些(我在前面提到过)。

更一般地说

class A
end

class Object
  def meta_def name, &blk
    (class << self; self; end).instance_eval { define_method name, &blk }
  end
end

greeting = 'hello'

Class.new A do
  meta_def :new_class_method do
    puts greeting + ' I am a class method'
  end
end.new_class_method
  #=> hello I am a class method
A类
终止
类对象
定义元定义名称(&blk)
(类你好,我是一个类方法
如果您觉得这很有用,请不要谢我,谢谢一些(我在中看到过)。

您也可以使用extend()撬开对象的单例类。调用extend(module)会将模块中的方法添加到调用对象(即接收方)的单例类中。因此,如果您调用extend(module)当self=A时,即在类A内部,则模块的方法将插入到A的单例类中,而A的单例类中的方法也称为A的类方法:

class A
end

greeting = "hello"

Class.new(A) do 

  extend(
    Module.new do
      define_method(:greet) do
        puts greeting
      end
    end
  )

end.greet

--output:--
hello
你可以这样重写它(尽管这样就没那么棘手了):

…这与:

class A
end

greeting = "hello"

m =  Module.new do
  define_method(:greet) do
    puts greeting
  end
end

Class.new(A) do 
  extend(m)
end.greet
…这会将闭包移出类,看起来一点也不复杂,因为它只打开两个范围门,而不是三个范围门

还要注意的是,extend()是一个公共方法,因此它不需要私有方法的技巧,也就是说,在不能指定显式接收方的情况下,因此必须创建一个上下文,其中self是要调用私有方法的对象。换句话说,可以为extend()指定显式接收方.类返回的类如何。新建(A)

嘿,钉上“.greet”就行了!哦,那有一行的气质:

class A
end

greeting = "hello"

Class.new(A).extend(Module.new {define_method(:greet) {puts greeting} }).greet

--output:--
hello
Yeech!

您还可以使用extend()撬开对象的单例类。调用extend(module)将模块中的方法添加到调用对象(即接收方)的单例类中。因此,如果您调用extend(module)当self=A时,即在类A内部,则模块的方法将插入到A的单例类中,而A的单例类中的方法也称为A的类方法:

class A
end

greeting = "hello"

Class.new(A) do 

  extend(
    Module.new do
      define_method(:greet) do
        puts greeting
      end
    end
  )

end.greet

--output:--
hello
你可以这样重写它(尽管这样就没那么棘手了):

…这与:

class A
end

greeting = "hello"

m =  Module.new do
  define_method(:greet) do
    puts greeting
  end
end

Class.new(A) do 
  extend(m)
end.greet
…这会将闭包移出类,看起来一点也不复杂,因为它只打开两个范围门,而不是三个范围门

还要注意的是,extend()是一个公共方法,因此它不需要私有方法的技巧,也就是说,在不能指定显式接收方的情况下,因此必须创建一个上下文,其中self是要调用私有方法的对象。换句话说,可以为extend()指定显式接收方.类返回的类如何。新建(A)

嘿,钉上“.greet”就行了!哦,那有一行的气质:

class A
end

greeting = "hello"

Class.new(A).extend(Module.new {define_method(:greet) {puts greeting} }).greet

--output:--
hello

Yeech!

我不认为这是Max问题的重点。他以字符串为例,但他想做的是将当前范围内的变量或方法的值合并到他定义的方法中。我不认为这是Max问题的重点。他以字符串为例,但他想做的是合并他正在定义的方法中当前范围内的变量或方法。