Skip to content

Instantly share code, notes, and snippets.

@rsliter
Created December 5, 2012 15:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rsliter/4216800 to your computer and use it in GitHub Desktop.
Save rsliter/4216800 to your computer and use it in GitHub Desktop.
Eigenclasses in Ruby
# The design pattern to create singleton CLASSES is pretty familiar-- it restricts the instantiation of a
# class to a single object. Eigenclasses in Ruby, however, allow you to restrict methods to a particular
# instance of a class. Eigenclasses also allow for restricted class methods.
#
# Hence, eigenclasses contain an object's singleton METHODS.
class Lupus
def is_a_wolf?
true
end
end
class Familiaris < Lupus
def bark
"Woof!"
end
end
# DEFINING THE EIGENCLASS
#
# Consider the biological classification for a dog (http://en.wikipedia.org/wiki/Dog).
# It has a species designation of "lupus" and a subspecies of "familiaris." All dogs share this.
rover = Familiaris.new
# Now I have an instance of Familiaris, named "rover." He has a trick that not many other dogs can do:
def rover.roll_over_three_times
"Rolling over three times"
end
rover.roll_over_three_times
# => "Rolling over three times"
old_dog = Familiaris.new
old_dog.roll_over_three_times
# => raises a NoMethodError -- you can't teach an old dog new tricks!
# Above, we defined a method directly on an instance of the Familiaris class (rover).
# The better way to define a singleton method is by opening up the eigenclass using the "<<" syntax:
class << old_dog
def new_trick
"New trick!"
end
end
old_dog.new_trick
# => "New trick!"
rover.new_trick
# => raises a NoMethodError
# METHOD LOOKUP
#
# If an object has an eigenclass, Ruby first looks in its eigenclass when a method is called.
# If the method is not in the eigenclass, Ruby goes further up the object chain to the eigenclass's superclass,
# which is the object's class. After that, the normal method lookup chain continues, all the way up to object.
# If there is no eigenclass, the method lookup will go straight to the object's class.
rover.bark
# Lookup chain: rover -> eigenclass -> Familiaris
rover.is_a_wolf?
# Lookup chain: rover -> Familiaris -> Lupus
rover.to_s
# Lookup chain: rover -> Familiaris -> Lupus -> Object
# EIGENCLASS CLASS METHODS
#
# Along with creation of singleton object methods, eigenclasses, because they are classes, can also have class
# methods. Recall that Familiaris is a subclass of Lupus:
class Lupus
class << self
def howl
"AOOOOOOOOOOOOOO"
end
end
end
Familiaris.howl
# => "AOOOOOOOOOOOOOO"
# The method lookup for this is kind of wonky: Familiaris checks its eigenclass; not finding the method
# definition, the its superclass (the eigenclass of Familiaris' superclass) is then checked for the method
# definition.
# Lookup chain: Familiaris -> eigenclass -> eigenclass of Lupus
# REFERENCES
#
# http://madebydna.com/all/code/2011/06/24/eigenclasses-demystified.html
# http://pragprog.com/downloads/1155010/dca2a145e604baeb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment