Overriding Class Methods With Modules

How do I override a class method on an object with another module? For
example:

class TestObject
def self.my_method
“override me”
end
end

module TestExtension
def my_method
“overridden by TestExtension”
end
def another_method
“another method”
end
end

TestObject.extend TestExtension

puts TestObject.my_method #=> “override me”
puts TestObject.another_method #=> “another method”

Why can’t I get TestObject to use my_method from TestExtension?

John W. Long wrote:

 def my_method

puts TestObject.another_method #=> “another method”

Why can’t I get TestObject to use my_method from TestExtension?

Because we don’t have Cuts :wink:

Okay a more presently practical answer. You can use a hack like:

module TestExtension
  def self.included(base)
    base.module_eval do
      def my_method
        "overridden by TestExtension"
      end
    end
  end
  def another_method
    "another method"
  end
end

T.

Trans wrote:

  def another_method
    "another method"
  end
end

Mmm. That doesn’t work either.

On 8/30/06, John W. Long [email protected] wrote:

Trans wrote:

Okay a more presently practical answer. You can use a hack like:

module TestExtension
  def self.included(base)

shouldn’t be “extended” ?

Hi –

On Wed, 30 Aug 2006, John W. Long wrote:

def my_method
puts TestObject.another_method #=> “another method”

Why can’t I get TestObject to use my_method from TestExtension?

What you’re seeing is that in the method lookup path, a given class
comes before any modules it includes. In your case, the class in
question is the singleton class of TestObject: that class defines
#my_method, and also includes a module that defines #my_method. The
one defined in the class “wins”.

Here’s another, parallel example:

module M
def my_method
puts “M#my_method”
end
end

class C
end

c = C.new

class << c # defined the method in the class
def my_method
puts “C#my_method”
end
end

c.extend(M) # also include the module in the class
c.my_method # “C#my_method” (the class wins)

The module would win if the method were defined in the class of the
object, rather than the singleton class – because then the lookup
order would be:

singleton class (no)
module included by singleton class (yes – execute method)
[class (never reached)]

David

That works. So the final code would be something like:

module TestExtension
def inject_methods(base)
base.module_eval do
def self.my_method
“overridden by TestExtension”
end
end
end

def extended(base)
inject_methods(base)
end

def included(base)
inject_methods(base)
end
end

This has always been a little clunky in Ruby, primarily because
methods written within a specific class were designed to override
mixin and parent class methods, not vice-versa.