Pop Quiz: aliasing versus wrapping

P

Phrogz

Below are two files that differ only in the 2nd line of code in each.
Can you guess what difference they will reveal? I must admit I was
surprised when I ran into this.

$ cat alias.rb
class Object
alias_method :to_js, :inspect
end

class Array
def to_js; "[#{map{|o|o.to_js}.join(',')}]"; end
end

class Hash
def to_js
"{#{map{|k,v| "#{k.to_s.to_js}:#{v.to_js}" }.join(',')}}"
end
end

[ 1, [true], {a:"foo"} ].each{ |o| puts o.to_js }

$ cat wrapped.rb
class Object
def to_js; inspect; end
end

class Array
def to_js; "[#{map{|o|o.to_js}.join(',')}]"; end
end

class Hash
def to_js
"{#{map{|k,v| "#{k.to_s.to_js}:#{v.to_js}" }.join(',')}}"
end
end

[ 1, [true], {a:"foo"} ].each{ |o| puts o.to_js }
 
R

Robert Klemme

2010/3/31 Phrogz said:
Below are two files that differ only in the 2nd line of code in each.
Can you guess what difference they will reveal? I must admit I was
surprised when I ran into this.

$ cat alias.rb
=A0class Object
=A0 =A0alias_method :to_js, :inspect
=A0end

This one always invokes Object#inspect - unless you override #to_js explici=
tly.
$ cat wrapped.rb
=A0class Object
=A0 =A0def to_js; inspect; end
=A0end

This is the one you really want IMHO: #to_js delegates to whatever
#inspect is present in the class.

Pretty straightforward inheritance behavior - although I'd concede
that it's subtle.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
M

Martin DeMello

Below are two files that differ only in the 2nd line of code in each.
Can you guess what difference they will reveal? I must admit I was
surprised when I ran into this.

It's pretty clear if you think of it in terms of message handlers and
method objects
=A0class Object
=A0 =A0alias_method :to_js, :inspect
=A0end

This binds the message handler Object#to_js to the method object
Object#inspect. This should be illustrative:

$ cat test.rb
class Object
alias_method :to_js, :inspect
alias_method :inspect, :hash
end

a =3D Object.new
puts a.inspect
p a
puts a.to_js

$ ruby test.rb
67266180
67266180
# said:
$ cat wrapped.rb
=A0class Object
=A0 =A0def to_js; inspect; end
=A0end

This creates a new method object, which contains a thunk that sends
the message "inspect" to self when it is invoked, and binds the
Object#to_js message handler to that method object.

martin
 
P

Phrogz

This one always invokes Object#inspect - unless you override #to_js explicitly.

Yes; specifically, in this case, Object#inspect on a String calls
#to_s (because it's defined), so:
puts "foo".to_js
#=> foo
instead of the desired "foo" (with quotes).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top