Skip to content

Instantly share code, notes, and snippets.

@snuggs
Created March 24, 2011 21:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save snuggs/885938 to your computer and use it in GitHub Desktop.
Save snuggs/885938 to your computer and use it in GitHub Desktop.
Meta Programming Made Easy
# Yehuda Katz - (It's all about the self)
# http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
#######################################################################################
# All classes are objects themselves
#######################################################################################
# Defining a class using the "class" keyword is merely syntactic sugar.
# All class definitions are actually instances of the Class object.
class MyClass; end # MyClass = Class.new
class ParentClass; end # ParentClass = Class.new
class ChildClass < ParentClass; end # MyClass = Class.new(ParentClass)
########################################################################################
# NOTICE: All classes in Ruby are open! Ruby code is interpreted. There is no compiler.
# Meaning they can be "reopened" and redefined at runtime.
# Hence why this code is valid if you run this file with the ruby interpreter
# (or paste this code into irb)
#######################################################################################
# open MyClass and define a Class (singleton) method in class definition
class MyClass
def self.my_class_method;end
end
# open String base class and define an instance method in class definition
class String
def i_can_haz_cheezburgr?
true
end
end
########################################################################################
# NOTICE: All objects are open as well. Methods can be defined on a particular instance (and its class).
# In this case a method is added to the instance's class; an Eigenclass (ghost, shadow class)
# is created which duplicates the class of the instance. This makes the method
# available to the instance and that instance ONLY!
#
# This "Eigenclass" cannot be accessed directly. (e.g. cannot be inherited)
#######################################################################################
# e.g.
my_class_instance = MyClass.new
def my_class_instance.method_for_this_instance_only
# MyClass is duplicated into an Eigenclass (ghost class)
# and this method definition is stored there.
return "I can only be accessed from this instance of MyClass"
end
my_class_instance.method_for_this_instance_only # => "I can only be accessed from this instance of MyClass"
# Notice: The class of my_class_instance is still MyClass. The Eigenclass(MyClass) is a ghost.
my_class_instance.class # => MyClass
another_my_class_instance = MyClass.new
another_my_class_instance.respond_to?(:method_for_this_instance_only) # => false
# Class (singleton) method defined outside of class definition
def MyClass.my_class_method; end
MyClass.my_class_method
# Multiple class (singleton) methods
class MyClass
# Use this style of metaprogramming to group 2 or more class methods
# instead of repeating def self.<method_name>; end
class << self # Define all methods on self's class (here self = MyClass)
def my_class_method; end
def my_second_class_method; end
end
def my_instance_method; end
end
MyClass.my_class_method
MyClass.my_second_class_method
MyClass.new.my_instance_method
################################################################################################
# ALL methods have a receiver
# To fully grok Ruby one must understand the "dot notation" within an object's method call
# <object>(dot)<method> # is equivelant to:
old_self = self
# self = <object>
# self.send(<method>.to_sym)
# self = old_self
################################################################################################
# e.g.
my_class_instance = MyClass.new
my_class_instance.my_instance_method # is equivelant to:
old_self = self
# self = my_class_instance
# self.send(:my_instance_method)
# self = old_self
# Same works for classes (since they are only object instances of Class.new)
MyClass.my_class_method # is equivelant to:
old_self = self
# self = MyClass
# self.send(:my_class_method)
# self = old_self
################################################################################################
# "This above all; to thine own SELF be true,
# and it must follow, as the night the day,
# thou canst not then be false to any [class]" - William Shakespeare
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment