method_missing结合instance_exec的奇怪行为(ruby)
我想让一个Foo
的实例执行一些方法或过程(不管),如果它或它的foo_instance
知道它。 foo_instance
是Foo
的一个实例,它定义了一些方法。我想,那个时候的Foo
另一个实例不响应一些方法,如果foo_instance
确实,它将在它的实例执行PROC:method_missing结合instance_exec的奇怪行为(ruby)
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}
这就是我结识了PROC与get_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
,因为它可能是一个参数数组,但我不确定。我无法让它工作。
确实是因为method_missing
签名中的*args
。这将保存通过的任何参数(第一个参数,即方法名称除外),并将它们放入数组中(1
- >[1]
)。为了解决这个问题,呼吁instance_exec
时只使用*
作为一吐操作:
self.instance_exec *args, &some_proc
谢谢!这是我错过的。 – medusa
我的理解是,你希望:
- 创建
Foo
类的实例
- 在
foo
的单身人员类别上创建一个或多个方法 - 时的
foo
的单例类的方法,m
一个符号被发送到boo
,的Foo
不同实例,并且boo
并不m
响应(即,m
既不是Foo
实例方法也没有在一个方法boo
的单身类),method_missing
将用于发送m
到foo
。
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
现在
boo.foo_method(1)
#=> 2
你块试图返回字符串''foo''?我无法在这里重现问题。你能想出一个你想在这里做什么的最简单的例子吗? – tadman