Your question led me to this interesting article which describes the problem:
Fixing Ruby’s Inheritance Model with Metamorph
This is the ultimate problem with Ruby’s inheritance model, in my opinion. Because mixins always take lower priority than methods defined directly in a class body, A#foo can not be overridden by mixin inclusion. Moreover, because mixins take lower priority than methods, A#foo is now violating encapsulation [...]
And his solution is to transparently define all new methods inside an anonymous inner module:
class Object
def self.method_added(name)
return if name == :initialize
const_set(:InstanceMethods, Module.new) unless defined?(self::InstanceMethods)
meth = instance_method(name)
self::InstanceMethods.send(:define_method, name) {|*args, &block| meth.bind(self).call(*args, &block) }
remove_method(name)
include self::InstanceMethods
end
end
This is also conveniently packaged in a library called metamorph, which allows you to have mixin methods override class methods by just requiring it.