Redefine modules?

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

···

--
Posted via http://www.ruby-forum.com/.

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

···

2009/2/11 Stanley Roberts <caseyandstanley@hotmail.com>:

  I am quite new to Ruby and make some experiences with modules and
classes. (...)

Pit Capitain wrote:

  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

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

···

2009/2/11 Stanley Roberts <caseyandstanley@hotmail.com>:

--
Posted via http://www.ruby-forum.com/\.

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

···

On Thu, Feb 12, 2009 at 8:11 AM, Stanley Roberts < caseyandstanley@hotmail.com> wrote:

Pit Capitain wrote:
> 2009/2/11 Stanley Roberts <caseyandstanley@hotmail.com>:
>> 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

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?

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

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

Regards,
Pit

···

2009/2/12 Rick DeNatale <rick.denatale@gmail.com>:

(...)
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.
(...)