From: ara.t.howard@... Date: 2007-01-31T14:51:23+09:00 Subject: Re: Tricks with method as superclass On Wed, 31 Jan 2007, Clifford Heath wrote: > I'm intrigued by the way Camping uses a method invocation to > serve as a superclass, and while exploring, possibly found a > bug? At any rate, some behaviour I can't explain... but first > a simple example of what Camping does: > > class Foo > def initialize(*args) > puts "Initializing Foo" > end > end > => nil > > def Foo(*args) > puts args.inspect > Class.new(Foo) # Interesting that this works... > end > => nil > > class Bar < Foo("Hi there!") > end > ["Hi there!"] > => nil > > Bar.new > Initializing Foo > => # > > Ok, all's well, and it's basically what Camping does. > Now what if I want to pass a *block* to the method > that will return my superclass? > > def Foo(*args, &block) > puts args.inspect > block.call if block > Class.new(Foo) > end > => nil > > class Bar < Foo("Hi There!") { > puts "Surprise!" > } > end > ["Hi there!"] > Surprise! > => nil > > Cool, that worked well. Now I want to keep the args and block passed > that was passed to the method, so I tried the following, which makes > an anonymous subclass of Foo, and Bar is a subclass of that: > > class Foo > def initialize(*args) > puts "Initializing Foo" > end > end > => nil > > def Foo(*args, &block) > puts args.inspect > block.call if block > Class.new(Foo).instance_eval <<-END > def initialize > # I'm going to do something with block and args here > puts "Double surprise!" > end > self > END > end > => nil > > class Bar < Foo("Hi there!") { > puts "Surprise!" > } > end > ["Hi there!"] > Surprise! > => nil > > Bar.new > Initializing Foo > => # > > What happened to my Double surprise? It seems that instance_eval hasn't > caused Bar.new to use my extra layer of initialize... The instance of > Bar has the anonymous superclass in it's hierarchy, but the initialize() > doesn't appear in the call stack. What gives here? harp:~ > cat a.rb class Foo def initialize(*args) puts "Initializing Foo" end end def Foo(*args, &block) puts args.inspect block.call if block # Class.new(Foo).instance_eval <<-END Class.new(Foo).module_eval <<-END def initialize # I'm going to do something with block and args here puts "Double surprise!" end self END end class Bar < Foo("Hi there!") { puts "Surprise!" } end Bar.new harp:~ > ruby a.rb ["Hi there!"] Surprise! Double surprise! regards. -a -- we can deny everything, except that we have the possibility of being better. simply reflect on that. - the dalai lama