kotp
11/16/2010 - 7:16 PM

Metaprogramming basics post code

Metaprogramming basics post code

require 'metaclass_mp'

class TheParent; end

class Child < TheParent
  def Child.the_eigenclass_method
    "Hi from #{self}"
  end
  def an_instance_method
    "Hi from #{self}"
  end
end

puts "Child's instance methods:              #{Child.instance_methods(false)}"
puts "Child's object id:                     #{Child.object_id}"
puts "Child's class:                         #{Child.class}"
puts "Child's superclass:                    #{Child.superclass}"
puts "Child's ancestors:                     #{Child.ancestors.join(', ')}"
puts '-'*20
puts "Child's singleton methods:             #{Child.singleton_methods(false)}"
puts '-'*20
puts "Child's metaclass instance_methods:    #{Child.metaclass.instance_methods(false).join(', ')}"
puts "Child's metaclass object id:           #{Child.metaclass.object_id}"
puts "Child's metaclass class:               #{Child.metaclass.class}"
puts "Child's metaclass superclass:          #{Child.metaclass.superclass}"
puts "Child's metaclass ancestors:           #{Child.metaclass.ancestors.join(', ')}"
class Person
  def Person.the_eigenclass_method
    "Hi from #{self}"
  end
  def an_instance_method
    "Hi from #{self}"
  end
end

# Person instances will have the methods defined in
# SomeClass.instance_methods(false), remember, a false
# parameter means that you only want to see the methods 
# defined in that Person class and not the inherited ones.
puts Person.instance_methods(false)

# With SomeClass.singleton_methods(false) you'll see the
# eigenclass methods. The false parameter indicates that 
# you only want to see the singleton methods defined in that
# class.
puts Person.singleton_methods(false)


class AnotherPerson
end

puts %{AnotherPerson singleton methods BEFORE: #{AnotherPerson.singleton_methods.join(', ')}}
puts %{AnotherPerson responds to a singleton method called "greet"?: #{AnotherPerson.singleton_methods.include?(:greet)}}

def AnotherPerson.greet
end

puts %{AnotherPerson singleton methods AFTER: #{AnotherPerson.singleton_methods.join(', ')}}
puts %{AnotherPerson responds to a singleton method called "greet"?: #{AnotherPerson.singleton_methods.include?(:greet)}}

class Person1
  def Person1.greet
    "hi from #{self}"
  end
end

puts Person1.greet

class Person2
  def self.greet
    "hi from #{self}"
  end
end

puts Person2.greet

class Person3
  class << self
    def greet
      "hi from #{self}"
    end
  end
end

puts Person3.greet
name = "maria"

puts "I don't have singleton methods look: [#{name.singleton_methods}]"

def name.jump
  "I'm #{self.capitalize} and I'm jumping"
end

puts "I have one singleton method: [#{name.singleton_methods}]"
puts name.jump

# If we create another string instace it won't respond to jump
new_name = "maria"
puts "#{new_name} jumps?: #{new_name.respond_to?(:jump)}"
require 'my_cheap_pretty_print'
# If the 'puts' syntax confuses you please look at my cheap pretty print for some help

puts [__LINE__, self, self.class, "I'm at program beginning"]
puts 

class Greeter
  def initialize
    puts [__LINE__, self, self.class, "This method is invoked on a Greeter instance."]
  end
  def greet
    puts [__LINE__, self, self.class, "This method is instance on a Greeter instance."]
    puts 'Hi from the greeter'
  end
end

puts [__LINE__, self, self.class, "I'm still the same object. But things are about to change."]
greet = Greeter.new
puts [__LINE__, self, self.class, "I'm again the same object."]

date = Time.new
def date.day
  puts [__LINE__, self, self.class, "I'm invoked on a Time instance."]
  super
end

puts [__LINE__, self, self.class, "I'm still the same object. But things are about to change."]
puts date.day
puts [__LINE__, self, self.class, "I'm again the same object."]
require 'my_cheap_pretty_print'
# If the 'puts' syntax confuses you please look at my cheap pretty print for some help

puts [__LINE__, self, self.class, "I'm at program beginning"]
puts 

class Greeter
  puts [__LINE__, self, self.class, "Class begin. Changing because of a class definition."]

  def initialize
    puts [__LINE__, self, self.class, "This method is invoked on a Greeter instance."]
  end

  puts [__LINE__, self, self.class, "Changing because of a class definition."]

  def greet
    puts [__LINE__, self, self.class, "This method is instance on a Greeter instance."]
    p 'Hi from the greeter'
  end

  puts [__LINE__, self, self.class, "Class end. Changing because of a class definition."]
end

puts 

puts [__LINE__, self, self.class, "I'm still the same object. But things are about to change."]
greet = Greeter.new
puts [__LINE__, self, self.class, "I'm again the same object."]
puts

module TestModule
  puts [__LINE__, self, self.class, "Module begin."]
  
  class InnerClass
    puts [__LINE__, self, self.class, "Inner class."]
  end

  puts [__LINE__, self, self.class, "Module middle."]

  module InnerModule
    puts [__LINE__, self, self.class, "InnerModule."]
  end

  puts [__LINE__, self, self.class, "Module end."]
end

puts
puts [__LINE__, self, self.class, "I'm again the same object."]
# My cheap pretty print is a 'puts' wrapper that strives to improve my examples
# output while reducing some puts duplicity. I know it isn't perfect, so feel free
# to send my any suggestions.
MESSAGE = "At line: [%d]. \n\tI'm self [%s] with class [%s]. \n\t\tNote that: '%s'"
DIVISION = '-'*50
COMMON_RESPONSE = '--Common response--> %s <--'

# Basically it means that when this file is included, 'puts' has only to
# purposes:
#
# 1 - If called without parameters it will print a diving line
# 2 - If called with exactly 4 parameters where first one is an integer line number,
#     remaining parameters are strings.
# The output is the formatted message from MESSAGE constant
def puts(*args)
  super MESSAGE % args[0] if args && args[0].is_a?(Array) && args[0].size == 4
  super DIVISION unless args[0]
  super COMMON_RESPONSE % args[0]
end
require 'metaclass_mp'
# Step 5
# If the was not method named "m" after completing the search, then a method named 
# method_missing is invoked instead. In order to find an appropriate definition of 
# this method, the name resolution algorithm starts over at step 1. The Kernel module 
# provides a default implementation of method_missing, so this second pass of name 
# resolution is guaranteed to succeed.

class StringParent < String; end
class MyString < StringParent
  def method_missing(method, *params)
    puts "The method #{method} was  not found"
  end
end

name = MyString.new("maria")

puts "#{name}'s jump: #{name.jump}"
require 'metaclass_mp'
# Step 4
# If the instance method "m" was not found in its class or in its modules, then the search 
# moves up the inheritance hierarchy of the super class. Step 2 and 3 are repeated for 
# each class in the inheritance hierarchy until each ancestor class and its included modules 
# have been searched.

class StringParent < String
  def jump
    "I'm jumping"
  end
end

class MyString < StringParent
end

name = MyString.new("maria")

puts "#{name}'s jump: #{name.jump}"
puts "Responds to :jump ?: [%s]" % name.respond_to?(:jump)
puts "Does name has any singleton methods?: [%s]" % !name.singleton_methods.empty?

MyString.ancestors.each do |ancestor|
  puts "Is :jump stored in ancestor \"#{ancestor}\"?: [%s]" % ancestor.instance_methods(true).include?('jump')
end
require 'metaclass_mp'
# Step 3
# If the method "m" is not found in its class, Ruby searches the instance methods of any 
# modules included by the "o"'s class. If there are modules included, they are searched in
# the reverse of the order in which they are included.

module Jumper
  def jump
    "I'm jumping"
  end
end

class String
  include Jumper
end

name = "maria"

puts "#{name}'s jump: #{name.jump}"
puts "Responds to :jump ?: [%s]" % name.respond_to?(:jump)
puts "Does name has any singleton methods?: [%s]" % !name.singleton_methods.empty?
puts "Is :jump stored in name's class?: [%s]" % String.instance_methods(true).include?('jump')
puts "What modules were included?: [%s]" % String.included_modules.join(', ')
require 'metaclass_mp'
# Step 2
# If the method named "m" is not found in the eigenclass, Ruby searches the in "o"'s class for an 
# instance method name "m".

class String
  def jump
    "I'm jumping"
  end
end

name = "maria"

puts "#{name}'s jump: #{name.jump}"
puts "Responds to :jump ?: [%s]" % name.respond_to?(:jump)
puts "Does name has any singleton methods?: [%s]" % !name.singleton_methods.empty?
puts "Is :jump stored in name's class?: [%s]" % String.instance_methods(true).include?('jump')
require 'metaclass_mp'
# Step 1
# As the first step, Ruby checks the eigenclass of "o" for singleton method named "m".

name = "Maria"

def name.jump
  "I'm jumping"
end

puts "#{name}'s jump: #{name.jump}"
puts "Responds to :jump ?: [%s]" % name.respond_to?(:jump)
puts "Does name has any singleton methods?: [%s]" % !name.singleton_methods.empty?
puts "Is :jump stored in name's eigenclass?: [%s]" % name.metaclass.instance_methods(true).include?('jump')
puts "Is :jump stored in name's class?: [%s]" % String.instance_methods(true).include?('jump')
class Object
  def metaclass
    class << self
      self
    end
  end
end

require 'my_cheap_pretty_print'
# If the 'puts' syntax confuses you please look at my cheap pretty print for some help
require 'metaclass_mp'

class Greeter
  def initialize(name)
    @name = name
  end
  def greet
    puts [__LINE__, self, self.class, "Inside an greet instance method"]
    "Hi"
  end
end

greeter = Greeter.new('Juanito')
puts greeter.greet

greeter.instance_eval do
  puts [__LINE__, self, self.class, "Inside an instance_eval"]
  puts [__LINE__, self, self.class, "And name equals: #{@name}"]
end

puts "Does it has any singleton methods?: [%s]" % !greeter.singleton_methods.empty?

greeter.instance_eval do
  def mexican_greet
    "Hola compa"
  end
end

puts "Responds to :mexican_greet ?: [%s]" % greeter.respond_to?(:mexican_greet)
puts "Does it has any singleton methods?: [%s]" % !greeter.singleton_methods.empty?
puts "Is :mexican_greet stored in greeter's eigenclass?: [%s]" % greeter.metaclass.instance_methods(true).include?('mexican_greet')
puts "Is :mexican_greet stored in greeter's class?: [%s]" % Greeter.instance_methods(true).include?('mexican_greet')
require 'my_cheap_pretty_print'
# If the 'puts' syntax confuses you please look at my cheap pretty print for some help

def greet
  # the implicit receiver is the "Object instance" main object
  puts [__LINE__, self, self.class, "I'm at the implicit receiver"]
  'Hi there'
end 

# the implicit receiver is the "Object instance" main object
puts [__LINE__, self, self.class, "I'm at the implicit receiver"]
puts greet

class Greeter
  def initialize
    # the implicit receiver will be the "Greeter instance" 'not yet created' greet  object
    puts [__LINE__, self, self.class, "I'm the implicit receiver at [#{__method__}] method"]
    greet
  end
  def greet
    # the implicit receiver will be the "Greeter instance" 'not yet created' greet object
    puts [__LINE__, self, self.class, "I'm the implicit receiver at [#{__method__}] method"]
    puts 'Hi from the greeter'
  end
end

greet = Greeter.new
def out_greet
  # Here the **implicit receiver** is the *main* object. It is an Object class instance
  # and it receives a *p* message.
  p 'Hi there'
end 

# Here the **implicit receiver** is the *main* object again. It is an Object class instance
# and it receives a *out_greet* message.
out_greet

class Greeter
  def initialize
    # the implicit receiver will be the "Greeter instance" 'not yet created' greet  object
    # Here the **implicit receiver** will be the *greeter instance* not yet created. It will be 
    # a Greeter class instance and it will receive a *greet* message.
    greet
  end
  def greet
    # Here the **implicit receiver** is the *main* object. It is an Object class instance
    # and it receives a *p* message.
    p 'Hi from the greeter'
  end
end

greet = Greeter.new
require 'my_cheap_pretty_print'
# If the 'puts' syntax confuses you please look at my cheap pretty print for some help

class Greeter
  def greet
    puts [__LINE__, self, self.class, "I'm the explicit receiver"]
    'Hi there'
  end 
end 

greeter = Greeter.new
# The explicit receiver is the "Greeter instance" greet object.
puts greeter.greet

person = 'Boni'
# The explicit receiver is the "String instance" person object.
def person.swapcase
  puts [__LINE__, self, self.class, "I'm the explicit receiver"]
  super
end
puts person.swapcase

date = Time.new
def date.day
  puts [__LINE__, self, self.class, "I'm the explicit receiver]"]
  super
end

# The explicit receiver is the "Time instance" date object.
puts date.day
class Greeter
  def greet
    p 'Hi there'
  end 
end 

greeter = Greeter.new
# Here the **explicit receiver** is the *greeter* object. It is a Greeter class instance
# and it receives a *greet* message.
greeter.greet

person = 'Boni'
# Here the **explicit receiver** is the *person* object. It is a String class instance
# and it receives a *swapcase* message.
p person.swapcase

# Here the **explicit receiver** is the *date* object. It is a Time class instance
# and it receives a *day* message.
date = Time.new
p date.day
require 'my_cheap_pretty_print'
# If the 'puts' syntax confuses you please look at my cheap pretty print for some help
require 'metaclass_mp'

class Greeter
  def initialize(name)
    @name = name
  end
  def greet
    puts [__LINE__, self, self.class, "Inside an greet instance method"]
    "Hi"
  end
end

greeter = Greeter.new('Juanito')
puts greeter.greet

greeter.instance_eval do
  puts [__LINE__, self, self.class, "Inside an instance_eval"]
  puts [__LINE__, self, self.class, "And name equals: #{@name}"]
end

puts "Does it has any singleton methods?: [%s]" % !greeter.singleton_methods.empty?

greeter.instance_eval do
  def mexican_greet
    "Hola compa"
  end
end

puts "Responds to :mexican_greet ?: [%s]" % greeter.respond_to?(:mexican_greet)
puts "Does it has any singleton methods?: [%s]" % !greeter.singleton_methods.empty?
puts "Is :mexican_greet stored in greeter's eigenclass?: [%s]" % greeter.metaclass.instance_methods(true).include?('mexican_greet')
puts "Is :mexican_greet stored in greeter's class?: [%s]" % Greeter.instance_methods(true).include?('mexican_greet')
class A
end

puts "--" + A.instance_methods(false).join(', ')

class A
  def otro
  end
end

puts A.instance_methods(false).join(', ') + "---"

A.class_eval do
  puts self
  def meth1
    "some"
  end
end

puts A.instance_methods(false)