我试图让Foo
的实例执行某个方法或proc(无论如何),如果它或它的foo_instance
知道它。 foo_instance
是Foo
的一个实例,它定义了一些方法。我想,当Foo
的另一个实例没有响应某个方法时,如果foo_instance
这样做,它将在其实例中执行proc:
class Foo
attr_accessor :foo_instance # this is an instance of Foo
def get_proc(symbol)
# ... a method that gets a proc (it has nothing to do with to_proc, and it is not binded to any thing, it only gets the code (as I'm only allowing to define new methods or accessors not directly, it doesn't matter)
end
def method_missing(symbol, *args, &block)
throw NoMethodError unless self.foo_instance.respond_to? symbol
some_proc = self.foo_instance.get_proc symbol
self.instance_exec args, &some_proc
end
end
例如,假设foo_instance响应一个名为foo_method
的方法,它接受一个参数,它应该是一个数字。并且假设,当我们定义foo_method
时:
self.define_singleton_method :foo_method, & proc {|a| a + 1}
这就是我用get_proc
了解proc的方法,当我定义方法时,我将它保存在变量中。无论如何:
another_instance = Foo.new
another_instance.foo_method(1) # it goes to method_missing
当它到达method_missing
时,通过调试我发现args
是[1]
,它确实:
self.instance_exec [1], proc { 'foo' }
当然:
TypeError: no implicit conversion of Fixnum into Array
问题是:我做错了什么?由于instance_exec
或method_missing
应该收到1
,而不是[1]
,我也不会发送数组!我认为这可能是因为*args
因为它可能是一个args数组,但我不确定。我无法使它发挥作用。
答案 0 :(得分:0)
确实是因为*args
签名中的method_missing
。这将保存传递的所有参数(第一个参数除外,它是方法名称)并将它们放在一个数组中(1
- > [1]
)。要解决此问题,请在调用*
时使用instance_exec
作为spat运算符:
self.instance_exec *args, &some_proc
答案 1 :(得分:0)
我的理解是你希望:
foo
Foo
foo
的单身类foo
的单件类方法m
的符号发送到boo
时,Foo
的另一个实例和{ {1}}不响应boo
(即,m
既不是m
的实例方法,也不是Foo
单例类中的方法, boo
用于将method_missing
发送至m
。如果这是正确的,foo
的访问者必须位于@foo_instance
的单例类中,因此它可用于Foo
的所有实例。因此,我们从以下开始。
Foo
现在让我们在class Foo
singleton_class.send(:attr_accessor, :foo_instance)
end
foo = Foo.new
#=> #<Foo:0x007ff90c00f278>
Foo.foo_instance = foo
Foo.foo_instance
#=> #<Foo:0x007ff90c00f278>
的单身类上定义一个方法:
foo
并创建foo.define_singleton_method :foo_method, & proc {|a| a + 1}
foo.foo_method(3)
#=> 4
的另一个实例:
Foo
当执行最后一个语句并且boo = Foo.new
#=> #<Foo:0x007fcd63968858>
boo.foo_method(1)
#=> NoMethodError: undefined method `foo_method' for #<Foo:0x007fcd63968858>
没有回复boo
时,我们希望将foo_method
与参数foo_method
一起发送到1
}。因此,我们可以按如下方式编写foo
:
method_missing
现在
class Foo
def method_missing(symbol, *args, &block)
instance = self.class.foo_instance
raise NoMethodError unless instance.respond_to? symbol
instance.send(symbol, *args, &block)
end
end