From: Brian Candler Date: 2002-10-27T21:46:28+09:00 Subject: Re: Things That Newcomers to Ruby Should Know (10/16/02) On Thu, Oct 24, 2002 at 12:42:20PM +0900, William Djaja Tjokroaminata wrote: > I think your example can be shortened to this: > > class S < String > def speak > puts "Hello, I contain: #{self}" > end > end > > a = S.new("one") > puts "a.class = #{a.class}" # a.class = S > puts "(a+'two').class = #{(a+'two').class}" # (a+'two').class = String > > Well, a "mechanical" explanation may be that class S calls the String > class '+' method, which *always* creates a new object of class > String. But is it good from the "philosophical" point of view that > > Class_A + Class_B = Class_B (or even some other Class_C) > > and not always Class_A? > > (I would care less if the method is other than '+'...) I also find this interesting, as it's a side-effect of subclassing I hadn't thought about. Somewhere deep in the innards of String#+ it is doing the equivalent of a String.new; should it be doing a self.class.new instead? Put more philosophically: is it the responsibility of a class author to consider the requirements of possible future subclasses, in particular to make sure that inherited methods have the 'right' behaviour in the context of a subclass? If not, then the subclass will end up having to wrap those methods - i.e. class S def +(arg) S.new(super) end end That's ugly, and it seems like it was hardly worth inheriting the method in the first place. [1] The 'new' method which was inherited by S (or at least gives the appearance of being inherited) doesn't need a wrapper though: S.new returns an S, not a String. Perhaps that's why it's surprising that the inherited S#+ returns a String not an S. Regards, Brian. [1] That doesn't apply to _all_ inherited methods - e.g. the inherited '<=>' is perfectly good - just methods which return String in this case