[LRUG] Can't hide instance method if defined in native extension?
Sean O'Halpin
sean.ohalpin at gmail.com
Mon Nov 14 06:23:13 PST 2011
On Sun, Nov 13, 2011 at 10:25 PM, Peter Vrabel <kybu at kybu.org> wrote:
> Hi guys,
>
> I recently came across a strange behavior. I would like to measure time
> spent executing Mysql statement, so I tried to hide 'execute' instance
> method of Mysql::Stmt and my first idea was to use my custom module that I
> include into Mysql::Stmt class. But then I found that I can't do that,
> original 'execute' method is always called. Here is a small edited snippet:
>
[snip example]
Hi,
As others have pointed out, including a module inserts methods above
the current class in the inheritance hierarchy so you can't use it to
override methods defined in that class. You can however use extend on
an instance to override methods defined in the class.
I generally use one of the following two methods. The first is a
'hygenic' version of alias_method in that you can use the same
technique in multiple included modules without worrying about whether
the method has been already aliased. It's clean but it's slow (the
bind is costly). The second (which I use more often) is to use extend
with super. You can even combine both methods together.
# 'hygenic' way to override method via include
class Foo
def foo(*args, &block)
p [Foo, :foo, args, block]
end
end
Foo.new.foo(1, 2, 3)
module Override
def self.included(other)
original_foo = other.instance_method(:foo)
other.class_eval {
define_method :foo do |*args, &block|
p Override
args = args.reverse
original_foo.bind(self).call(*args, &block)
end
}
end
end
class Foo
include Override
end
Foo.new.foo(1, 2, 3)
# using extend
class Bar
def foo(*args, &block)
p [Bar, :foo, args, block]
end
end
module Extension
def foo(*args, &block)
p Extension
args = args.map{ |x| x.to_s}
super
end
end
b = Bar.new
b.extend(Extension)
b.foo(1, 2, 3)
# using both together
f = Foo.new
f.extend(Extension)
f.foo(1, 2, 3)
Running this gives you the following output:
$ ruby override-method.rb
[Foo, :foo, [1, 2, 3], nil]
Override
[Foo, :foo, [3, 2, 1], nil]
Extension
[Bar, :foo, ["1", "2", "3"], nil]
Extension
Override
[Foo, :foo, ["3", "2", "1"], nil]
HTH,
Sean
More information about the Chat
mailing list