当我有以下内容时:
class Foo
def bar
puts "#{__method__} was called and found within #{self}"
end
def method_missing(meth, *args, &blk)
puts "#{meth} was called and was not found within #{self}"
end
end
foo = Foo.new
foo.bar
# => bar was called and found within #<Foo:0x100138a98>
foo.baz
# => baz was called and was not found within #<Foo:0x100138a98>
我假设在找到方法时,方法调度看起来有点像:
foo.bar was asked to be called
Search methods defined within #<Foo:0x100138a98>
Method `bar` found
Call the `bar` method
对于未找到的方法:
foo.baz was asked to be called
Search methods defined within #<Foo:0x100138a98>
Method `baz` not found
Search methods defined within the parent of #<Foo:0x100138a98>
Method `baz` not found
And so on until it hits the parent that has no parent
Loop back around and see if #<Foo:0x100138a98> has a `method_missing` method defined
Method `method_missing` found
Call the `method_missing` method
我想这样介入:
foo.bar was asked to be called
Search methods defined within #<Foo:0x100138a98> to see it has a `method_dispatched` method
Method `method_dispatched` found
Calling `method_dispatched`
Search methods defined within #<Foo:0x100138a98>
...
这将允许开发人员执行以下操作:
class Foo
def bar
puts "#{__method__} was called and found within #{self}"
end
def method_missing(meth, *args, &blk)
puts "#{meth} was called and was not found within #{self}"
end
def method_dispatched(meth, *args, &blk)
puts "#{meth} was called within #{self}..."
puts "continuing with the method dispatch..."
end
end
foo = Foo.new
foo.bar
# => bar was called within #<Foo:0x100138a98>...
# => continuing with the method dispatch...
# => bar was called and found within #<Foo:0x100138a98>
foo.baz
# => bar was called within #<Foo:0x100138a98>...
# => continuing with the method dispatch...
# => baz was called and was not found within #<Foo:0x100138a98>
这让我想到了这个问题..
这可能吗?
答案 0 :(得分:0)
我不知道你正在寻找的回调。我会在Ruby Delegators上阅读一个可能的解决方案,它比我在下面描述的更优雅。
您可以在method_missing上包装对象和拦截。
class A
def foo
puts "hi there, I'm A"
end
end
maybe have B inherit A?
class B
def initialize
@a = A.new
end
def method_missing(m, *args, &block)
puts "hi there, I'm in B"
@a.send(m, *args, &block) if @a.respond_to? m
puts "all done"
end
end
答案 1 :(得分:0)
这里有一个Ruby初学者的排序,但我有一些有效的解决方案。所以如果你认为某些东西不是红宝石,请对代码进行评论。
这个想法是为你拥有的方法和undef_method原始方法的别名。这将为您的所有实例方法创建一个别名。然后,您可以使用method_missing调用method_dispatched,然后调用实际方法。
class Test
def foo
"foo"
end
def method_dispatched(meth, *args, &blk)
puts "#{meth} was called within #{self}..."
puts "continuing with the method dispatch..."
end
def method_missing(name, *args, &block)
method_dispatched(name, args, block) #Calls your standard dispatcher
if (respond_to?('_' + name.to_s)) # Check if we have a aliased method
send('_' + name.to_s)
else
"undef" #Let the caller know that we cant handle this.
end
end
instance_methods(false).each do |meth|
if meth != 'method_missing' and meth != 'method_dispatched'
alias_method "_#{meth}", meth
remove_method(meth)
end
end
end
t = Test.new
puts t.foo()
puts t.undefined_method()