# Tricks with method as superclass

**URL:** <https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981>\
**Category:** Ruby\
**Created:** [January 31, 2007, 6:35am UTC](https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981 "2007-01-31T06:35:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Clifford\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Clifford\_H](https://www.ruby-forum.com/u/Clifford_H)\
**Post date:** [January 31, 2007, 6:35am UTC](https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981/1 "2007-01-31T06:35:32Z")

</div>

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  
=\> #Bar:0x2f84358

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  
=\> #Bar:0x2f776b0

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 H…

---

<div class="post-metadata">

**Author:** ![Clifford\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Clifford\_H](https://www.ruby-forum.com/u/Clifford_H)\
**Post date:** [January 31, 2007, 6:51am UTC](https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981/2 "2007-01-31T06:51:33Z")

</div>

On Wed, 31 Jan 2007, Clifford H. wrote:

> ```
> => nil
> => nil
> 
> ```
> 
> puts args.inspect  
> Surprise!  
> end  
> self  
> =\> nil
> 
> Bar.new  
> Initializing Foo  
> =\> #Bar:0x2f776b0
> 
> 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

---

<div class="post-metadata">

**Author:** ![Clifford\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Clifford\_H](https://www.ruby-forum.com/u/Clifford_H)\
**Post date:** [January 31, 2007, 6:59am UTC](https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981/3 "2007-01-31T06:59:33Z")

</div>

> 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

This is really cool. Regarding the double surprise problem, class\_eval  
instead of instance\_eval (and a call to super) does the trick:

Class.new(Foo).class\_eval \<\<-END  
def initialize  
super  
# I’m going to do something with block and args here  
puts “Double surprise!”  
end  
self  
END

=\> [“Hi there!”]  
Surprise!  
Initializing Foo  
Double surprise!

–max

---

<div class="post-metadata">

**Author:** ![Clifford\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Clifford\_H](https://www.ruby-forum.com/u/Clifford_H)\
**Post date:** [January 31, 2007, 7:30am UTC](https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981/4 "2007-01-31T07:30:35Z")

</div>

removed\_email\_address@domain.invalid wrote:

> ```
> # Class.new(Foo).instance_eval <<-END
> Class.new(Foo).module_eval <<-END
> 
> ```

Thanks Ara - super-quick response too! Caught out by the singleton,  
which I didn’t expect to find on a Class instance. Here’s a complete  
example that shows most of what’s possible, assuming the attachment  
comes through.

Clifford H…

---

<div class="post-metadata">

**Author:** ![Clifford\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/49beb7/32.png) [@Clifford\_H](https://www.ruby-forum.com/u/Clifford_H)\
**Post date:** [January 31, 2007, 7:55am UTC](https://www.ruby-forum.com/t/tricks-with-method-as-superclass/83981/5 "2007-01-31T07:55:36Z")

</div>

Max M. wrote:

> This is really cool.

Thanks, I agree. Ara beat you to it, but I thought I’d  
post a simpler example too. The cute thing about this is  
that you can use method\_missing magic to make the attached  
block use a different DSL than the class body.

$ cat superclass-method-simple.rb  
class Foo  
def initialize(\*args)  
puts “Initializing a Foo”  
end  
end

def Foo(\*args, &block)  
Class.new(Foo).class\_eval \<\<-END  
@@\_args = args  
@@\_block = block  
def initialize  
super  
puts @@\_args.inspect  
@@\_block.call if @@\_block  
end  
self  
END  
end

class Bar \< Foo(“Hi there!”) {  
puts “Surprise!”  
}  
end

puts “All ready, here goes:”  
Bar.new

$ ruby superclass-method-simple.rb  
All ready, here goes:  
Initializing a Foo  
[“Hi there!”]  
Surprise!  
$

Cute, huh? 🙂
