From: Brian Adkins Date: 2008-12-12T02:43:12+09:00 Subject: Re: why Hash corrupts 'key' object ? Robert Klemme writes: > 2008/12/11 Dmitry Perfilyev : >> Hi, I have next script: >> t.rb: >> =========================== >> class TestStr < String >> attr_accessor :dupstr >> def initialize ( str ) >> @dupstr = str >> super(str) >> end >> end >> ts=TestStr.new("aaa") >> puts ts.dupstr >> h=Hash.new() >> h[ts]=true >> puts h.keys.first.class >> puts h.keys.first >> puts h.keys.first.dupstr >> =========================== >> >> run it: >> >> $ ruby t.rb >> aaa >> TestStr >> aaa >> nil >> $ >> >> The question is - why there is 'nil' in the last line instead of "aaa" ? > > Because Hash copies #dup an unfrozen String. Why would that cause this effect though? The docs say "a String passed as a key will be duplicated and frozen", but duplicating and freezing a TestStr doesn't nullify dupstr: $ cat -n temp.rb 1 class TestStr < String 2 attr_accessor :dupstr 3 def initialize ( str ) 4 @dupstr = str 5 super(str) 6 end 7 end 8 ts=TestStr.new("aaa") 9 puts ts.dupstr, ts.object_id 10 puts '---' 11 ts2 = ts.dup 12 ts2.freeze 13 puts ts2.dupstr, ts2.object_id $ ruby temp.rb aaa 81910 --- aaa 81880 > > http://www.ruby-doc.org/core/classes/Hash.html#M002878 > > Try this: > > class TestStr < String > attr_accessor :dupstr > def initialize ( str ) > @dupstr = str > super(str) > end > end > ts=TestStr.new("aaa") > puts ts.dupstr, ts.object_id > h=Hash.new() > h[ts]=true > puts h.keys.first.class, h.keys.first, h.keys.first.object_id, > h.keys.first.dupstr > puts "----" > ts.freeze > puts ts.dupstr, ts.object_id > h=Hash.new() > h[ts]=true > puts h.keys.first.class, h.keys.first, h.keys.first.object_id, > h.keys.first.dupstr > > It is generally a bad idea to inherit core classes. Delegation is > much better (see Mike's reply). > > Cheers > > robert > > > -- > remember.guy do |as, often| as.you_can - without end > -- Brian Adkins http://www.lojic.com/ http://lojic.com/blog/