Robert Klemme wrote:
> 2009/10/16 lith <minilith / gmail.com>:
>>> But I think the spirit of dup
>>> described above is that dup defined in a subclass should initialize it
>>> using its constructor.
> 
> Brian, I disagree.  The proper way is to implement #initialize_copy.
> That way you can make sure you do not get aliasing effects even if
> source and copy are frozen because in #initialize_copy frozen state is
> not applied.

I don't understand what you mean by that. If #dup calls self.class.new 
then you obviously get a new and hence unfrozen object.

It is certainly true that the *default* implementation of both #dup and 
#clone (defined in Object) calls initialize_copy. A generic #dup must 
behave this way; it doesn't know what the new() method arguments are in 
any particular subclass of Object. I don't think this should be taken as 
necessarily implying that you are expected to leave #dup alone in your 
own classes, and only override #initialize_copy instead.

The way I read the documentation implies to me that #dup in user defined 
classes *should* call new. Silly example:

  class NewsReader
    def initialize(url, state_filename)
      @url = url
      @http_client = HTTPClient.new(@url)
      @state_filename = state_filename
      @state_file = File.open(@state_filename)
    end
    def dup
      self.class.new(@url, @state_filename.dup)
    end
  end

Here the logic of how to build a NewsReader, including building all the 
associated helper objects, is built into the #initialize method. I don't 
think you would want to duplicate all this logic in #initialize_copy. 
Furthermore, I think I would expect #clone only to copy the top object, 
and leave all the instance variables aliased.

Obviously there are no hard-and-fast rules here, and with Ruby there are 
many ways to achieve the same goal.

I'd certainly agree this is an area where Ruby's documentation falls 
short.

Taking another example: I don't think you'll disagree that 99% of the 
time you are expected to leave Object.new alone and instead define 
#initialize in your own classes. But you wouldn't find that out from the 
documentation:

$ ri Object.new
------------------------------------------------------------ Object::new
     Object::new()
------------------------------------------------------------------------
     Not documented

$ ri Object#initialize
Nothing known about Object#initialize

-- 
Posted via http://www.ruby-forum.com/.