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