Ruby 通过const_动态创建名为的类
我有这个模块:Ruby 通过const_动态创建名为的类,ruby,binding,anonymous-class,Ruby,Binding,Anonymous Class,我有这个模块: module Api module ObjectMapper def self.const_missing const_name anon_class = Class.new do def self.foo puts self.class.name end end const_set const_name, anon_class end end end 我希望能够
module Api
module ObjectMapper
def self.const_missing const_name
anon_class = Class.new do
def self.foo
puts self.class.name
end
end
const_set const_name, anon_class
end
end
end
我希望能够在运行时使用foo
方法定义一个匿名类,该方法可以通过Api::ObjectMapper::User::foo
调用。该功能应将用户
打印到屏幕上。我所尝试的一切都导致了某种错误,或者函数将Class
打印到屏幕上
如何修复类和方法定义,以便正确解析self.class.name?我找到了一个解决方案。由于您是在const_missing方法的范围内定义匿名类,因此您可以使用const_name,它是您定义的类的名称。我不确定这是否是最好的解决方案,但它确实有效。你必须像这样重新定义你的类:
anon_class = Class.new do
define_singleton_method(:foo) do
puts const_name
end
end
我找到了解决办法。由于您是在const_missing方法的范围内定义匿名类,因此您可以使用const_name,它是您定义的类的名称。我不确定这是否是最好的解决方案,但它确实有效。你必须像这样重新定义你的类:
anon_class = Class.new do
define_singleton_method(:foo) do
puts const_name
end
end
您还可以将foo方法定义为类方法
def self.const_missing const_name
anon_class = Class.new do
def self.foo
puts self.class.name
end
end
end
您还可以将foo方法定义为类方法
def self.const_missing const_name
anon_class = Class.new do
def self.foo
puts self.class.name
end
end
end
类的名称只是引用它的第一个常量。原始代码的唯一问题是使用的是
self.class.name
,而不是self.name
:
module Api
module ObjectMapper
def self.const_missing const_name
self.const_set const_name, Class.new{
def self.foo
name.split('::').last
end
}
end
end
end
p Api::ObjectMapper::User, #=> Api::ObjectMapper::User
Api::ObjectMapper::User.name, #=> "Api::ObjectMapper::User"
Api::ObjectMapper::User.foo #=> "User"
定义类方法(类上的单例方法)时,self
就是类。因此,self.class
始终是class
,其名称是“class”
原始答案,返回“User”,而不是“Api::ObjectMapper::User” 一种方法(不比基于闭包的解决方案更好)是在类上使用实例变量:
module Api
module ObjectMapper
def self.const_missing const_name
anon_class = Class.new do
def self.foo
puts @real_name
end
end
anon_class.instance_variable_set(:@real_name,const_name)
const_set const_name, anon_class
end
end
end
Api::ObjectMapper::User.foo
#=> User
两个可选的更紧密的语法:
def self.const_missing const_name
const_set const_name, Class.new{
def self.foo; puts @real_name end
}.tap{ |c| c.instance_eval{ @real_name = const_name } }
end
def self.const_missing const_name
const_set const_name, Class.new{
def self.foo; puts @real_name end
}.instance_eval{ @real_name = const_name; self }
end
类的名称只是引用它的第一个常量。原始代码的唯一问题是使用的是
self.class.name
,而不是self.name
:
module Api
module ObjectMapper
def self.const_missing const_name
self.const_set const_name, Class.new{
def self.foo
name.split('::').last
end
}
end
end
end
p Api::ObjectMapper::User, #=> Api::ObjectMapper::User
Api::ObjectMapper::User.name, #=> "Api::ObjectMapper::User"
Api::ObjectMapper::User.foo #=> "User"
定义类方法(类上的单例方法)时,self
就是类。因此,self.class
始终是class
,其名称是“class”
原始答案,返回“User”,而不是“Api::ObjectMapper::User” 一种方法(不比基于闭包的解决方案更好)是在类上使用实例变量:
module Api
module ObjectMapper
def self.const_missing const_name
anon_class = Class.new do
def self.foo
puts @real_name
end
end
anon_class.instance_variable_set(:@real_name,const_name)
const_set const_name, anon_class
end
end
end
Api::ObjectMapper::User.foo
#=> User
两个可选的更紧密的语法:
def self.const_missing const_name
const_set const_name, Class.new{
def self.foo; puts @real_name end
}.tap{ |c| c.instance_eval{ @real_name = const_name } }
end
def self.const_missing const_name
const_set const_name, Class.new{
def self.foo; puts @real_name end
}.instance_eval{ @real_name = const_name; self }
end
看起来你在追求一些非常甜蜜的元编程,但我无法理解你的最终愿望。感谢您包含您的代码尝试。你能从总结你想要发生的事情开始吗?展示一些你想运行的代码和你想产生的结果。我简化了问题。希望现在更清楚了。可能的副本看起来你在追求一些非常甜蜜的元编程,但我无法理解你的最终愿望。感谢您包含您的代码尝试。你能从总结你想要发生的事情开始吗?展示一些你想运行的代码和你想产生的结果。我简化了问题。希望现在更清楚了。可能是重复的