I'm having a herp-derpy moment. I could've sworn this worked:
module StubbedGreeting
def sayit
puts "StubbedGreeting"
end
end
module RegularGreeting
def sayit
puts "RegularGreeting"
end
end
class Greeting
def sayit
raise "Gotta catch me!"
end
end
class GreetingIncludes
include RegularGreeting
end
begin
Greeting.send(:include, StubbedGreeting)
Greeting.new.sayit
rescue Exception
puts "Exception raised"
end
GreetingIncludes.send(:include, StubbedGreeting)
GreetingIncludes.new.sayit
What happens here is Greeting.new.sayit results in in the rescue block being called, ignoring the attempted overwrite by StubbedGreeting.
However, GreetingIncludes.new.sayit results in "StubbedGreeting", not an exception.
So a module can overwrite another module's methods, but not methods already defined directly in the class?
I know how to finagle my way around this, I just found it weird.
When including a module, it's methods are put between the methods of the class and it's parent class in the method resolution order. So when resolving which actual method is to be called, ruby first searches for the method in the following order. If a matching method is found, the search is aborted and this method is used.
This then continues for each parent class until the Class class is reached.
As you can see, the modules can indeed not override methods defined on a class itself as modules come behind the actual class in the method resolution order. If you really need to override such a method, you can use alias_method or alias_method_chain to "rename" methods.
In the upcoming Ruby 2.0 there will be a prepend mechanism which will include modules before the class which will achieve what you want. But it's not released yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With