views:

45

answers:

2

I was looking through some code in a string escape library the other day and I came across some code that looks like this:

class StringWrapper 
  class << self
    alias new_no_dup new
    def new(str)
      new_no_dup(str.dup)
    end
  end

  def initialize(str)
    @str = str
  end

  ...

end

Can anyone explain exactly what is going on here? I understand up to the class << self part, but I don't quite understand aliasing the method new to new_no_dup, only to call it in the new method below? Also, why do you think the author want to do this in this manner?

+3  A: 

By aliasing new_no_dup to new, the original new functionality can be called by calling new_no_dup.

The StringWrapper.new method calls duplicate (.dup) on the provided string and then provides that copy to the original StringWrapper.new method.

As for why, I would assume the author is trying to prevent the original string from being changed. StringWrapper will always have it's own string in memory.

Jason Noble
+1  A: 

Whether you use .dup on strings influences whether in-place modifications (methods ending with !) affect the original string.

As a silly little demonstration...

irb(main):009:0> def shout(s)
irb(main):010:1>  local = s.dup
irb(main):011:1>  local.upcase!
irb(main):012:1>  puts local
irb(main):013:1> end
=> nil
irb(main):014:0> greeting = "hi"
=> "hi"
irb(main):015:0> shout(greeting)
HI
=> nil
irb(main):016:0> greeting
=> "hi"

If you run the same snippet, changing local = s.dup to local = s, then the final value of greeting will be "HI" because shout will have modified greeting. .dup returns a copy of the original string, preventing modifications to the original.

Mark Rushakoff