Overriding Class Methods With Modules

J

John W. Long

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?
 
T

Trans

John said:
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?

Because we don't have Cuts ;-)

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.
 
J

John W. Long

Trans said:
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

Mmm. That doesn't work either.
 
D

dblack

Hi --

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?

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

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
A

Aleks Kissinger

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top