6

Is there a way to override a class's operator, by creating a new operator method inside a module, then mixing that module into the class?

eg, this overrides Fixnum's + operator:

class Fixnum def +(x) product = x product = product * self return product end end p 3 + 3 # => 9 

This does not override Fixnum's + operator:

module NewOperators def +(x) product = x product = product * self return product end end class Fixnum include NewOperators end p 3 + 3 # => 6 
1

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

3

No, because in a method lookup you don't get a chance to pull in methods that were defined in mixins or parent classes until you've actually looked at the current class.

That said, you can create a method that, when called on a class, will create methods in that class. This can give you a way to inject operators into classes easily.

Be warned that actually doing this is a good recipe for surprise. This is doubly true when you are changing standard modules whose behavior is relied upon by others. See http://avdi.org/devblog/2008/02/23/why-monkeypatching-is-destroying-ruby/ for context.

1 Comment

Interesting article! I can see how monkey patching would get out of hand for large projects.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.