Created
November 16, 2010 19:16
-
-
Save chischaschos/702312 to your computer and use it in GitHub Desktop.
Metaprogramming basics post code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Object | |
def metaclass | |
class << self | |
self | |
end | |
end | |
end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(', ') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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."] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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."] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)}} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(', ')}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment