Hooks and Classes

After watching episode 6 “Some Hook Methods” of the Pragmatic Screencasts of The Ruby Object Model and Metaprogramming with Dave Thomas I wrote some methods for Class.


class Class
  def inherited(subklass)
    puts "class #{subklass.inspect} desends from #{self.inspect}" 
  end

  original_new = instance_method(:new)

  define_method(:new) do |*args|
    puts "#{self}.new called" 
    original_new.bind(self).call(*args)
  end

  class << self
    original_new = instance_method(:new)

    define_method(:new) do |*args|
      puts "#{self}.new called with #{args.inspect}" 
      original_new.bind(self).call(*args)
    end
  end
end

What happens in IRB?


~ irb -r class.rb
IRB::Irb.new called
IRB::Context.new called
IRB::WorkSpace.new called
IRB::ReadlineInputMethod.new called
IRB::StdioOutputMethod.new called
RubyLex.new called
IRB::SLex.new called
IRB::SLex::Node.new called
IRB::SLex::Node.new called
IRB::SLex::Node.new called
# ... 72 lines of "IRB::SLex::Node.new called" 
IRB::SLex::Node.new called
IRB::SLex::Node.new called
IRB::SLex::Node.new called
>>

That’s quite a lot of nodes.

Let’s see what happens when classes are created.


>> class Q;end
RubyToken::TkCLASS.new called
RubyToken::TkSPACE.new called
RubyToken::TkCONSTANT.new called
RubyToken::TkSEMICOLON.new called
RubyToken::TkEND.new called
RubyToken::TkNL.new called
class Q desends from Object
=> nil
>> Class.new(Q)
RubyToken::TkCONSTANT.new called
RubyToken::TkDOT.new called
RubyToken::TkIDENTIFIER.new called
RubyToken::TkLPAREN.new called
RubyToken::TkCONSTANT.new called
RubyToken::TkRPAREN.new called
RubyToken::TkNL.new called
Class.new called with [Q]
Class.new called
class #&lt;Class:0x53c654&gt; desends from Q
=> #&lt;Class:0x53c654&gt;

The new method is not used to create every object.


>> [nil]
RubyToken::TkLBRACK.new called
RubyToken::TkNIL.new called
RubyToken::TkRBRACK.new called
RubyToken::TkNL.new called
=> [nil]
>> Array(1)
RubyToken::TkCONSTANT.new called
RubyToken::TkLPAREN.new called
RubyToken::TkINTEGER.new called
RubyToken::TkRPAREN.new called
RubyToken::TkNL.new called
=> [1]
>> Array.new(1)
RubyToken::TkCONSTANT.new called
RubyToken::TkDOT.new called
RubyToken::TkIDENTIFIER.new called
RubyToken::TkLPAREN.new called
RubyToken::TkINTEGER.new called
RubyToken::TkRPAREN.new called
RubyToken::TkNL.new called
Array.new called
=> [nil]

This has been an exercise into hooks and to see what classes are created.

Leave a Reply