我的代码中存在一些范围问题,我真的不知道如何解决它们。
我有这段代码
class MainClass
def methodOfMainClass
#do something
end
def test obj
obj.instance_variables.map do |attribute|
obj.define_singleton_method(:something) do |arg|
self.methodOfMainClass()
end
end
end
当我执行它时,引发 NoMethodError :未定义的方法`methodOfMainClass'为
#<Obj:0x0035f6274c9g12>
但是methodOfMainClass不是来自Obj,而是来自MainClass。如何在 define_singleton_method 方法中引用正确的类?
答案 0 :(得分:2)
在ruby中self
是一种方法,而不是参考。在调用self
然后运行它的对象中创建单例方法时,它将在运行时引用该对象,而不是创建该方法的对象。
这里有一些能够满足你所要求的东西,尽管我无法想象它的用例。使您想要在MainClass中调用的方法成为类的单例方法(类方法),然后调用它从另一个对象的单例方法命名该类。
class OtherClass
def initialize(ivar1: nil, ivar2: nil)
@ivar1 = ivar1
@ivar2 = ivar2
end
end
class MainClass
def self.methodOfMainClass
puts "method #{__method__} called"
end
def test(obj)
obj.instance_variables.map do |attribute|
method_name = attribute.to_s.gsub(/@/,'')
obj.define_singleton_method(method_name) do |arg|
puts "#{__method__} called with #{arg}"
MainClass.methodOfMainClass
end
end
end
end
my_instance = MainClass.new
other = OtherClass.new(ivar1: 'hello', ivar2: 'world')
my_instance.test(other)
other.ivar1('something')
other.ivar2('else')
输出:
ivar1 called with something
method methodOfMainClass called
ivar2 called with else
method methodOfMainClass called
或者,如果您因某些原因不想创建类方法,可以在单例方法定义之外创建对self的引用并在其中使用:
class OtherClass
def initialize(ivar1: nil, ivar2: nil)
@ivar1 = ivar1
@ivar2 = ivar2
end
end
class MainClass
def methodOfMainClass
puts "method #{__method__} called"
end
def test(obj)
ref = self
obj.instance_variables.map do |attribute|
method_name = attribute.to_s.gsub(/@/,'')
obj.define_singleton_method(method_name) do |arg|
puts "#{__method__} called with #{arg}"
ref.methodOfMainClass
end
end
end
end
my_instance = MainClass.new
other = OtherClass.new(ivar1: 'hello', ivar2: 'world')
my_instance.test(other)
other.ivar1('something')
other.ivar2('else')
输出与之前相同,但只要MainClass的实例超出范围,这将失败。