From: Rick DeNatale Date: 2009-02-13T01:33:03+09:00 Subject: Re: Redefine modules? --00163628395e1ec4be0462bb4a1b Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit On Thu, Feb 12, 2009 at 8:11 AM, Stanley Roberts < caseyandstanley@hotmail.com> wrote: > Pit Capitain wrote: > > 2009/2/11 Stanley Roberts : > >> 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? 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 -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale --00163628395e1ec4be0462bb4a1b--