"Chr. Rippel" <chr_news / gmx.net> wrote:
> ... I would not expect
> that subclassing modifies the return value of a method unless it is a
> self-modifing like String#capitalize! or Array#sort! or one of the
> fundamental copying methods Object#copy and Object#dup.
>
> A good example is
> -----
> class List < Array; end
> i = 0
> L = List.new(5).collect!{ i+=1 }
> p    L.type                                         # => List
> p    L.select   {|i|  i % 2 == 0 }.type   # => Array
> p    L.collect  {|i|  i*i }.type              # => Array
> p    L.collect! {|i|  i*i }.type              # => List
> ----

I don't think it is a bad thing if all of operations above to return
Lists -- after all Lists *are* Arrays. If Lists are proper subtypes of Array
you would never know the difference. Of course it should be well defined in
the subclass's interface what type it returns. My issue is not about
returning instances of the subclass so much as returning broken objects.

> Anyway in your particular example it does not seem apparent
> if  sub_indexing  makes a copy of your instance variable or not -

Viewing this at slightly higher level, one could assume that it should
return a non-broken object. If instance variables have to be initialized to
certain values to achieve that, then it should be so. Clearly it broke the
inspect method in my example.

> i.e. it seems to me that your responsibility to say
>
> ----
> class S < String
>     # your example
>     def [](r)
>         (res = super(r)).otherValue = @otherValue        # or
>         #  (res = super(r)).otherValue = @otherValue.dup #
>         return res
>      end
>     protected
>     attr_writer :otherValue
> end
> ----

Yes the situation could be fixed by overriding the offending operations. But
I kind of get the impression that having superclasses return subclass types
is mainly to shortcut the need for doing a lot of overriding. In methods you
override you can easily have them return subclass types, so what other
advantage is there to the existing behavior?


Bob