#http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

class Object
  # The hidden singleton lurks behind everyone
  def metaclass; class << self; self; end; end
  def meta_eval(&blk)
    metaclass.instance_eval(&blk)
  end

  # Adds methods to a metaclass
  def meta_def name, &blk
    meta_eval { define_method name, &blk }
  end

  # Defines an instance method within a class
  def class_def name, &blk
    class_eval { define_method name, &blk }
  end
end

class A
  def cheese
    'shropshire blue'
  end

  def self.cheese
    'edam'
  end
end

class B < A
  def cheese
    'cheddar'
  end

  def self.cheese
    'stilton'
  end
end

a = A.new
b = B.new
b_with_meta = B.new
b_with_meta.meta_def(:cheese) {'cheshire'}

b_with_meta_meta = B.new
b_with_meta_meta.meta_def(:cheese) {'brie'}
b_with_meta_meta.metaclass.meta_def(:cheese) {'gouda'}
b_with_meta_meta.metaclass.metaclass.meta_def(:cheese) {'wensleydale'}


puts "A.cheese: #{A.cheese}"
puts "B.cheese: #{B.cheese}"
puts "a.cheese: #{a.cheese}"
puts "b.cheese: #{b.cheese}"
puts "b_with_meta.cheese: #{b_with_meta.cheese}"
puts "b_with_meta.metaclass.cheese: #{b_with_meta.metaclass.cheese}"
puts "b_with_meta_meta.cheese: #{b_with_meta_meta.cheese}"
puts "b_with_meta_meta.metaclass.cheese: #{b_with_meta_meta.metaclass.cheese}"
puts "b_with_meta_meta.metaclass.metaclass.cheese: #{b_with_meta_meta.metaclass.metaclass.cheese}"