Redefine modules?

S

Stanley Roberts

Hi,
I am quite new to Ruby and make some experiences with modules and
classes.
I have defined a module and an inner class with the same name (Cucc) and
a static method (x) for the class. Then I made a redefinition (or
whatever you call) of the same module (Cucc) without the inner class but
with a static (x) method.

Before the redefinition x method of the Cucc module's inner class Cucc
is called but right after the modules static method is called. Why?

I totally agree that coding style like below is among the first 10 on
the list to avoid during programming, but though I want to understand
the behavior!

I have created the following code:
------CODE START-----------
module Cucc
def Cucc.x(arg)
puts arg.to_s + " Cucc.x"
end
def x(arg)
puts arg.to_s + " Cucc module x"
end
class Cucc
def Cucc.x(arg)
puts arg.to_s + " Cucc module Cucc class Cucc.x"
end
def x(arg)
puts arg.to_s + " Cucc module Cucc class x"
end
end
end

puts "Cucc class started first"
Cucc::x(10)
c = Cucc::Cucc.new
c.x(20)
Cucc::Cucc.x(30)
puts "Cucc class ended first"

module Cucc
def Cucc.x(arg)
puts arg.to_s + " Redefined Cucc module Cucc.x"
end
def x(arg)
puts arg.to_s + " Redefined Cucc module x"
end
end

puts "Cucc class started second"
Cucc::x(10)
c = Cucc::Cucc.new
c.x(20)
Cucc::Cucc.x(30)
puts "Cucc class ended second"
------CODE END-----------

The outcome is the following:
Cucc class started first
10 Cucc.x
20 Cucc module Cucc class x
30 Cucc module Cucc class Cucc.x
Cucc class ended first
Cucc class started second
10 Cucc.x
20 Cucc module Cucc class x
30 Redefined Cucc module Cucc.x
Cucc class ended second

How the hell is it possible that for the "30" that I get different
result when having a redefinition (or so) of the Cucc module?

At first the inner class' static method is called and in the second case
the static method of the module!

Thanks in advanced, --stan--
 
P

Pit Capitain

2009/2/11 Stanley Roberts said:
I am quite new to Ruby and make some experiences with modules and
classes. (...)

Stan, maybe the following code will give you some hints:

module Cucc
puts Cucc.class # => Module
class Cucc; end
puts Cucc.class # => Class
end

It has to do with the way Ruby resolves the names of constants.

Regards,
Pit
 
S

Stanley Roberts

Pit said:
Stan, maybe the following code will give you some hints:

module Cucc
puts Cucc.class # => Module
class Cucc; end
puts Cucc.class # => Class
end

It has to do with the way Ruby resolves the names of constants.

Regards,
Pit

Hi Pit,
it's OK, but I still don't understand what is the situation when
overriding a module.

I have added the class method to check what happens:
Cucc::Cucc.x(30) # => 30 Cucc module Cucc class Cucc.x
puts Cucc::Cucc # => Class

But after the redefinition of the same module (without having the Cucc
innerclass) the same lines lead to different outcome:
Cucc::Cucc.x(30) # => 30 Redefined Cucc module Cucc.x
puts Cucc::Cucc # => Class

Can you please explain me this?

Thanks in advance --stan--
 
R

Rick DeNatale

[Note: parts of this message were removed to make it a legal post.]

Stan, maybe the following code will give you some hints:

module Cucc
puts Cucc.class # => Module
class Cucc; end
puts Cucc.class # => Class
end

It has to do with the way Ruby resolves the names of constants.

Regards,
Pit

Hi Pit,
it's OK, but I still don't understand what is the situation when
overriding a module.

I have added the class method to check what happens:
Cucc::Cucc.x(30) # => 30 Cucc module Cucc class Cucc.x
puts Cucc::Cucc # => Class

But after the redefinition of the same module (without having the Cucc
innerclass) the same lines lead to different outcome:
Cucc::Cucc.x(30) # => 30 Redefined Cucc module Cucc.x
puts Cucc::Cucc # => Class

Can you please explain me this?[/QUOTE]


You've got two or three misconceptions here.

First, you seem to assume that redefining a method won't lead to a different
outcome. Why else would you redefine a method? In ruby redefining a method
replaces that method, so you'll get the new version when you invoke it. So
the real question is why aren't you seeing the OTHER redefinition, which is
the second misconception.

Second, in your test code you are never calling the second x method. This
method will only be accessible in an instance of a class which includes the
Cucc module. So you might want to add

class Test
include Cucc
end

test = Test.new
before your "started first"

and then add test.x(40) to each of your sets of calls, this should show that
when you call it you do get the redefined method.

Now, what might seem strange is that you might think that it should be the
Cucc::x(10)

which invokes the other redefined method, after all first you wrote:

module Cucc
def Cucc.x(...
end

and wrote the same thing in the redefinition, this is the third
misconception, that the meaning of Cucc WITHIN the module means the same
thing in both cases, it doesn't.

I'm not sure whether or not you are really confused about this is because of
the string produced in the overriden method. I'm not sure whether you are
documenting your intention or your surprise with the result.

The way Ruby resolves 'global' names is that it starts looking for the name
in the current module, and if it doesn't find it, it looks for the same name
in the enclosing name scope.

So in this case, it will first look for ::Cucc::Cucc (where the initial ::
indicates the outermost name scope), then it will look for ::Cucc

The first time, before what you are calling the inner class (which by the
way is a Java concept not directly transferrable to Ruby) doesn't exist, so
it doesn't find ::Cucc::Cucc and you end up defining a singleton method of
the Cucc module.

The second time, it does find ::Cucc::Cucc so you end up redefining the
instance method x in Cucc::Cucc.

If you really wanted to redefine the ::Cucc#x you should right the
redefinition as either:

module Cucc
def self.x(arg)
puts arg.to_s + " Redefined Cucc module.x"
end
#...
end

or outside of the module reopening

def Cucc.x(arg)
puts arg.to_s + " Redefined Cucc module.x"
end


HTH
 
P

Pit Capitain

2009/2/12 Rick DeNatale said:
(...)
and wrote the same thing in the redefinition, this is the third
misconception, that the meaning of Cucc WITHIN the module means the same
thing in both cases, it doesn't.
(...)

Thanks Rick for the detailed explanation. As you know I've been too
involved in some other threads lately :)

Regards,
Pit
 

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,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top