In data 3/13/2005, "Sam Roberts" <sroberts / uniserve.com> ha scritto: >Quoting ruby-ml / magical-cat.org, on Mon, Mar 14, 2005 at 06:08:35AM +0900: >> >I think Str#downcase should return the same thing as String#downcase => >> >a String, and not a Str, so I don't see why there is a recursive call, >> >here. >> >> When you derive, you establish an is_a relationship. Str is_a String. >> All methods are also derived so you're actually calling Str#downcase, >> although the code being executed was defined in String. > >I don't think thats the answer, its not how things normally work. static VALUE rb_str_downcase(str) VALUE str; { str = rb_str_dup(str); rb_str_downcase_bang(str); return str; } VALUE rb_str_dup(str) VALUE str; { VALUE dup = str_alloc(rb_obj_class(str)); rb_str_replace(dup, str); return dup; } It may not seem intuitive but it's conceptually exactly how it's supposed to go. >String#to_s doesn't work that way, for example, despite the docs saying >it does, it returns an object of class String, even if the receiver >isn't of class String. > >It looks like String.upcase is creating a new instance of its derived >class, but somehow bypassing the derived classes initialize, see example >below. > > >I don't understand how it does this. I thought it might be calling >self.class.new, but it doesn't. > >For example, how would I do this so it has the same behaviour as >#downcase, returning an object of the derived class: > > > class String > def brackets > self.class.new("(" + self + ")") > end > end > >The above doesn't work, so how would I do it? Hm, maybe self.copy.tr(..) >is what its doing... > >I guess I should read the String src code. > >Cheers, >Sam > > >Run the following through irb. > > >class String > def brackets > self.class.new("(" + self + ")") > end >end > >class Str < String > def initialize(s) > puts '!Str' > super(s) > end >end > > >class Now < String > def initialize > puts '!Now' > super(Time.now.to_s) > end >end > >class Now2 < String > def initialize(a,b) > puts "!Now2 #{a} #{b}" > super(Time.now.to_s) > end >end > >Str.new('aa').upcase >Str.new('aa').upcase.class >Now.new.upcase >Now.new.upcase.class >Now2.new(1,2).upcase >Now2.new(1,2).upcase.class > >Str.new('aa').brackets >Now.new.brackets >Now2.new(1,2).brackets > > >Str.new('aa').to_s.class >Now.new.to_s.class >Now2.new(1,2).to_s.class E