From: Clifford Heath Date: 2007-01-31T14:35:07+09:00 Subject: Tricks with method as superclass 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? Clifford Heath.