From: Bob Alexander Date: 2002-01-26T02:05:45+09:00 Subject: Subrange of String subclass => invalid object This is a multi-part message in MIME format. ------=_NextPart_000_01E8_01C1A57F.A8C4BD60 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Given these conditions: - A subclass of String or Array is defined - A superclass "subrange" operation is performed on an instance of the = subclass (e.g. object[1 ... -1]) In the general case, the result of the operation is an invalid instance = of the subclass. More specifically, if the subclass has its own instance = variables, they are uninitialized. For example, this code: ----------------------------------------- class S < String def initialize(str, otherValue) super(str) @otherValue =3D otherValue end def inspect "S(otherValue: " << @otherValue.to_s << ", " << super << ")" end end s =3D S.new("abcdefghij", 77) ss =3D s[1 ... -1] p s p ss ----------------------------------------- produces the following output: ----------------------------------------- S(otherValue: 77, "abcdefghij") ./rbug.rb:7: warning: instance variable @otherValue not initialized S(otherValue: , "bcdefghi") ----------------------------------------- Is this the intended consequence? For me it violated the "principle of = least surprise". This behavior means: o If my subclass has instance variables, I must override the = subscripted operations to add my instance variables to the result. o If I want to return an instance of the superclass from such an = operation, I have to "downcast" it by creating a new object of the = superclass type (e.g. String.new(self[1 ... -1])). (Of course, it really = *is* an instance of the superclass with its class changed.) This has probably been discussed to death in the past (I'm not always = tuned in to the list), but the advantages of a superclass returning = (likely invalid) subclass instances are not without their downsides! Bob ------=_NextPart_000_01E8_01C1A57F.A8C4BD60 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
Given these conditions:
 
  - A subclass of String or Array = is=20 defined
  - A superclass "subrange" = operation is=20 performed on an instance of the subclass (e.g. object[1 ... = -1])
 
In the general case, the result of the = operation is=20 an invalid instance of the subclass. More specifically, if the subclass = has its=20 own instance variables, they are uninitialized.
 
For example, this code:
 
-----------------------------------------
class S < String
  def initialize(str,=20 otherValue)
    super(str)
    = @otherValue =3D=20 otherValue
  end
  def = inspect
   =20 "S(otherValue: " << @otherValue.to_s << ", " << super = <<=20 ")"
  end
end
 
s =3D S.new("abcdefghij", 77)
ss =3D = s[1 ...=20 -1]
p s
p ss
-----------------------------------------
 
produces the following = output:
 
-----------------------------------------
S(otherVal= ue: 77,=20 "abcdefghij")
./rbug.rb:7: warning: instance variable @otherValue not = initialized
S(otherValue: , "bcdefghi")
-----------------------------------------
 
Is this the intended consequence? For me it violated the "principle = of=20 least surprise".
 
This behavior means:
 
o   If my subclass has instance variables, I must = override the=20 subscripted operations to add my instance variables to the result.
 
o   If I want to return an instance of the superclass = from such=20 an operation, I have to "downcast" it by creating a new object of the = superclass=20 type (e.g. String.new(self[1 ... -1])). (Of course, it really *is* an = instance=20 of the superclass with its class changed.)
 
This has probably been discussed to death in the past (I'm not = always tuned=20 in to the list), but the advantages of a superclass returning (likely = invalid)=20 subclass instances are not without their downsides!
 
 
Bob
------=_NextPart_000_01E8_01C1A57F.A8C4BD60--