• 20 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 10/4/17

Dive Into Classes, Modules, and Singletons

Log in or subscribe for free to enjoy all this course has to offer!

 

Get ready for a deep dive into Ruby's classes. In this chapter we're tying together classes, singletons, inheritance, and modules into one big picture, so this is an especially long video, but it's worth the time. If you find yourself getting lost, take a break, backtrack, and maybe follow along with the text in your own irb session. Once you understand the material in this chapter, you'll have formed a solid foundation for understanding everything else in Ruby. 

 

Classes are Objects too

Last chapter we talked about how objects work in Ruby. Each object is a collection of data, or instance variables, and has access to functions, or methods, through another object called it's class.

In this chapter we'll spend more time talking about the class objects, and the methods that they hold for use by other objects.

To see what methods a class provides for its instances, we can send the class object the messageinstance_methods:

irb:main> String.instance_methods
=> [:include?, :%, :unicode_normalize, :*, :+, :unicode_normalize!, :to_c, :unicode_normalized?, :count, :partition, :unpack, :encode, :encode!, :next, :casecmp, :insert, :bytesize, :match, :succ!, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :+@, :-@, :setbyte, :getbyte, :<=>, :<<, :scrub, :scrub!, :byteslice, :==, :===, :dump, :=~, :downcase, :[], :[]=, :upcase, :downcase!, :capitalize, :swapcase, :upcase!, :oct, :empty?, :eql?, :hex, :chars, :split, :capitalize!, :swapcase!, :concat, :codepoints, :reverse, :lines, :bytes, :prepend, :scan, :ord, :reverse!, :center, :sub, :freeze, :inspect, :intern, :end_with?, :gsub, :chop, :crypt, :gsub!, :start_with?, :rstrip, :sub!, :ljust, :length, :size, :strip!, :succ, :rstrip!, :chomp, :strip, :rjust, :lstrip!, :tr!, :chomp!, :squeeze, :lstrip, :tr_s!, :to_str, :to_sym, :chop!, :each_byte, :each_char, :each_codepoint, :to_s, :to_i, :tr_s, :delete, :encoding, :force_encoding, :sum, :delete!, :squeeze!, :tr, :to_f, :valid_encoding?, :slice, :slice!, :rpartition, :each_line, :b, :ascii_only?, :to_r, :hash, :<, :>, :<=, :>=, :between?, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :!~, :respond_to?, :display, :object_id, :send, :method, :nil?, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

Wow! That's a lot of methods.

Now let's compare that to a (related) method that you can call on any instance, calledmethods.methodssimply names all the methods that object has access to, through the "backpack" of its class object:

my_string.methods
=> [:include?, :%, :unicode_normalize, :*, :+, :unicode_normalize!, :to_c, :unicode_normalized?, :count, :partition, :unpack, :encode, :encode!, :next, :casecmp, :insert, :bytesize, :match, :succ!, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :+@, :-@, :setbyte, :getbyte, :<=>, :<<, :scrub, :scrub!, :byteslice, :==, :===, :dump, :=~, :downcase, :[], :[]=, :upcase, :downcase!, :capitalize, :swapcase, :upcase!, :oct, :empty?, :eql?, :hex, :chars, :split, :capitalize!, :swapcase!, :concat, :codepoints, :reverse, :lines, :bytes, :prepend, :scan, :ord, :reverse!, :center, :sub, :freeze, :inspect, :intern, :end_with?, :gsub, :chop, :crypt, :gsub!, :start_with?, :rstrip, :sub!, :ljust, :length, :size, :strip!, :succ, :rstrip!, :chomp, :strip, :rjust, :lstrip!, :tr!, :chomp!, :squeeze, :lstrip, :tr_s!, :to_str, :to_sym, :chop!, :each_byte, :each_char, :each_codepoint, :to_s, :to_i, :tr_s, :delete, :encoding, :force_encoding, :sum, :delete!, :squeeze!, :tr, :to_f, :valid_encoding?, :slice, :slice!, :rpartition, :each_line, :b, :ascii_only?, :to_r, :hash, :<, :>, :<=, :>=, :between?, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :!~, :respond_to?, :display, :object_id, :send, :method, :nil?, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

This output is really hard to read, but if you look closely at both arrays, you can see that the output ofmy_string.methodsis the same as the output ofString.instance_methods.

irb(main):> my_string.methods == String.instance_methods
=> true

 

The classClass

Last chapter we also discussed the fact that classes are objects themselves, and that therefore they also used methods, just as any object does. One of these was the methodnew, that allowed them to create new members of their "scout troop":

irb(main):> my_string = String.new
=> ""

In fact, we can call the methodmethodson a class object, just as we did on a string instance above, to see what the class itself can do:

String.methods
=> [:try_convert, :new, :allocate, :superclass, :<=>, :module_exec, :class_exec, :<=, :>=, :==, :===, :include?, :included_modules, :ancestors, :name, :public_instance_methods, :instance_methods, :private_instance_methods, :protected_instance_methods, :const_get, :constants, :const_defined?, :const_set, :class_variables, :class_variable_get, :remove_class_variable, :class_variable_defined?, :class_variable_set, :private_constant, :public_constant, :singleton_class?, :deprecate_constant, :freeze, :inspect, :module_eval, :const_missing, :prepend, :method_defined?, :class_eval, :public_method_defined?, :private_method_defined?, :<, :public_class_method, :>, :protected_method_defined?, :private_class_method, :to_s, :autoload, :autoload?, :instance_method, :public_instance_method, :include, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :=~, :!~, :eql?, :respond_to?, :display, :object_id, :send, :method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

Take a moment to make sure the difference is clear here betweenString.methods, andString.instance_methods.

String.instance_methodstells you the contents of String's own backpack, the one it can't access for its own use!String.methods, on the other hand, tells you the contents of the backpack held by String's own class, who is confusingly calledClass.

All class objects, such asString,Float,Array,Object, and any classes you or a 3rd party defines in your code, are all instances ofClass.

irb(main):> String.class
=> Class
irb(main):> Float.class
=> Class
irb(main):> Object.class
=> Class

 

Now, if you're following this logic closely, you might notice an inconsistency. If objects can't go in their own backpacks for methods, what about thisClassobject itself? where does it get its methods?

irb(main):> Class.class
=> Class

At this point the language cheats.Classis a contortionist who can reach into their own backpack! It's an exception that makes the language work.Classis the only class object in Ruby that has access to its own "backpack" of instance methods.

So let's list the methods that the Class class provides to its instances, the other class objects:

irb(main):> Class.instance_methods
=> [:new, :allocate, :superclass, :<=>, :module_exec, :class_exec, :<=, :>=, :==, :===, :include?, :included_modules, :ancestors, :name, :public_instance_methods, :instance_methods, :private_instance_methods, :protected_instance_methods, :const_get, :constants, :const_defined?, :const_set, :class_variables, :class_variable_get, :remove_class_variable, :class_variable_defined?, :class_variable_set, :private_constant, :public_constant, :singleton_class?, :deprecate_constant, :freeze, :inspect, :module_eval, :const_missing, :prepend, :method_defined?, :class_eval, :public_method_defined?, :private_method_defined?, :<, :public_class_method, :>, :protected_method_defined?, :private_class_method, :to_s, :autoload, :autoload?, :instance_method, :public_instance_method, :include, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :=~, :!~, :eql?, :respond_to?, :display, :object_id, :send, :method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

 

Inheritance

This list of methods we're printing out is really hard to read, but a brief scan of Class's instance methods reveals something interesting. There are some methods in there that are used by lots of other objects, not just classes. For example, compare the methods above with the instance methods available to members of the generic classObject:

irb(main)> Object.instance_methods
=> [:instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :<=>, :===, :=~, :!~, :eql?, :respond_to?, :freeze, :inspect, :display, :object_id, :send, :to_s, :method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :==, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

In fact, if you were concerned with reading this horrible output closely, you could find every single method listed byObject.instance_methodsin the list listed byClass.instance_methods.

This makes sense intuitively given that we've said all classes are objects. But how do the instances of classClassalso have access to the instance methods of classObject? Remember that each object has one, and only one class.

In order to share a set of methods across multiple classes, Ruby gives you two options: inheritance, and composition.

We'll look at composition in a bit, but the example we're looking at now uses inheritance to share the methods of theObjectclass with instance of theClassclass.

The parent class, akasuperclass

Inheritance works by giving every class a parent class. The parent class' "backpack" of methods then becomes available to the instance of the child class.

To say that another way: when the instances of a child class come looking for a method in their class's backpack and don't find it, they are directed to the class' "parent" class, orsuperclassof their class, and are allowed to use the method if it exists there.

For example, we used the methodmethodsearlier to list the names of theStringclass' methods.methodsis, itself, an instance method defined inObject 's instance methods (akaObject's "backpack"), and made available toStringthrough inheritance:

irb(main):> String.methods
=> [:try_convert, :new, :allocate, :superclass, :<=>, :module_exec, etc...
irb(main):> String.class
=> Class
irb(main):> Class.superclass
=> Module
irb(main):> Module.superclass
=> Object

When we callString.methods, the objectStringfirst looks to its class,Class, for a method called "methods".Classdoesn't have anything called "methods" in its backpack, but it does have a parent class (orsuperclass), calledModule, soStringgoes and looks inModule's backpack. There's nothing called "methods" inModule's backpack either, butModulehas its own parent class,Object, soStringnow goes to look inObject's backpack, and it finally finds its method there. In this case, there's an "inheritance chain" fromObjecttoClassthat looks like this:

Class < Module < Object

The inheritance chain can be as long as you want, although its a good idea to keep it short. The members of this inheritance chain can be thought of as ancestors of a class.

Declaring inheritance in your classes

When you define classes you can set their parent class with a less-than sign, like this:

class FireBuilderClassObject < Object
  def light_a_fire
    "it's burning now"
  end
end

Here we're inheriting from theObjectclass explicitly. In factObjectis a basic class that almost all other classes in Ruby descend from. It's like the hypothetical common ancestor of all humans, Eve: it's in everyone's family tree.

In fact,Objectis so basic that, if you don't explicitly inherit from anything in your class definitions, your class will automatically inherit fromObject! This means that appending  < Objectto your class definitions is always redundant, so if you're going to inherit fromObject, you can just leave it off..

Overwriting inherited methods, and thesuperkeyword

One important basic feature of inheritance is the ability to overwrite the methods of a superclass, but still be able to reference them.

When you define a method of the same name as an inherited one, your method replaces the inherited one. However, inside that method, you have access to to the method you're replacing via thesuperkeyword.

class DampFireBuilderClassObject < FireBuilderClassObject
  def light_a_fire
    "I used lighter fluid and " + super
  end
end

another_object = DampFireBuilderClassObject.new
another_object.light_a_fire
=> "I used lighter fluid and it's burning now"

Here the call tosuper, inside thelight_a_firemethod on theDampFireBuilderClassObjectclass, will look inside the parent class,FireBuilderClassObjectfor a method calledlight_a_fireand return whatever that method yields.DampFireBuilderClassObject#light_a_firecan then use that value without knowing the details of the implementation inFireBuilderClassObject.

To see how this can be used, try changing the superclass's method to return something different, without changing theDampFireBuilderClassObjectclass at all:

class FireBuilderClassObject
  def light_a_fire
    "it didn't light"
  end
end

another_object.light_a_fire
=> "I used lighter fluid and it didn't light"

 

Notice that we didn't have to instantiate our object again in the above example, or do anything to it for it to suddenly reflect the new behavior of its class. You can just open up a class definition and change it in the middle of your program, and it works immediately for all of the class's instances. This is an unusual feature of Ruby, but it follows from what we know about classes. Since instances access methods by "borrowing" them out of common class objects' "backpacks", changing the method that's in the class' "backpack" changes its behavior for all the instances that use it.

Singletons and "class methods"

There's just one piece of this puzzle that's still missing. If you look back at the beginning of last chapter, you'll see that we defined methods using an "explicit receiver". That is, instead of defining them inside a class definition and leaving off the receiver, we specified that we wanted our methods to belong tomy_object, like this:

def my_object.this_is_my_message
  "Hi, thanks for your message."
end

my_object.this_is_my_message
=> "Hi, thanks for your message."

But we've since said that methods can't belong to objects that use them, they have to be "held" by another object, the class.

When we usedefto define a method on an object, then, we might expect that it actually doesn't get added to that object, but to that object's class in some way.

To go back to our scouts analogy, it's like one of the scouts from the troop who builds fires was suddenly given a new tool only for themselves to use – perhaps some lighter fluid – that was useful for them. However, since campers aren't allowed to carry their own tools, they have to store it in a backpack somewhere that they will have access to the next time they need to build a fire.

As we understand it so far, it means the tool would have to be stored in the fire builder's class, or on one of their class's ancestor classes (ie, it's parent class, or that parent class' parent class, etc).

However storing the tool there would mean that anyone else with access to that pack would have access to the tool. In Ruby's terms, this would mean that all other instances of the object's class would gain the method. But that's not what this means of writing methods does. Consider:

irb:

my_first_object = Object.new
my_second_object = Object.new

def my_first_object.foo
  "bar"
end

my_first_object.foo
=> "bar"

my_second_object.foo
NoMethodError: undefined method `foo' for #<Object:0x007fccd51f1d88>
        from (irb):2
        from /Users/alegscogs/.rbenv/versions/2.0.0-p353/bin/irb:12:in `<main>'

It looks like the other objects in the Object class don't have access to this newfoomethod. We can test this another way, by looking directly at the instance methods we create:

my_object = Object.new

Object.instance_methods
=> [:nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

def my_object.foo
  "bar"
end

my_object.foo
=> "bar"

Object.instance_methods
=> [:nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

 

:fooseems to be unique tomy_object, and in a way, it is. This seems to fly in the face of what we've said about how classes and objects work, but it's possible because of a curious workaround in Ruby.

Singleton classes are invisible friends

Our analogy is going to have to get weird to support this, but what Ruby actually does in this case, is to provide all our scouts with invisible little sidekicks that have backpacks of their own!

These sidekicks are devoted to the object they work with, and only ever work with one object for their lifetime. That is, no other object, not even other member's of their object's class, can access the invisible sidekick's backpack. Perhaps for this reason, these objects are called singleton classes (or, sometimes, an eigenclass, which is a German name for the same thing).

Singleton classes are actually classes who's parent is the object's class. When you ask a Ruby object to perform one of its methods, what it actually does is ask its sidekick, or singleton class, for the method (or tool) in question. The sidekick, if they have that tool in their pack, will immediately produce it for the object's use.

The singleton sidekicks live a weird life as classes, though, because they don't have any real instances.

If you ask an object for a method, it asks its singleton class, who then generally goes and asks its parent class for the method. But if you ask an object who their class is (ie, where they get their methods from) they won't say: "my sidekick is my class object".

Instead, they'll tell you that their class is the one that actually instantiated, or created them. If you want to see what an object's singleton class is, instead of calling the "class" method on it, you can call this methodsingleton_class:

hidden_class = my_object.singleton_class
=> #<Class:#<Object:0x007fdb68805930>>

You can see that it's a class of its own:

hidden_class.class
=> Class

And as such can hold instance methods of its own.

We can see the instance methods that a class has defined on itself (excluding all the methods that may come from ancestor classes and modules) by passingfalseas an argument when we callinstance_methods:

hidden_class.instance_methods(false)
=> [:foo]

 

Aha! So that's where ourfoomethod is hiding.

This may seem obscure, and in fact most objects don't make much use of their sidekick helpers. Usually, they're just uselessly following along waiting to be given something cool to keep in their backpack, but that never happens.

Classes typically use their singleton class "sidekicks" to hold special instance methods for themselves to use.

One of the most common uses of singleton "sidekicks" is to hold instance methods for use by class objects.

Remember that each class is an instance of the classClass. This means that they all share the same methods, which are available on the classClass. They include things likenewandinstance_methods, which we've been using in this chapter to see "what's in their backpack of tools".

But class objects sometimes need methods of their own.

For example, the camper carrying the backpack for the fire builders might keep a record of how many times her flint was used to start a fire. After all, it might need to be replaced after a while.

SinceFireBuilderclass is an object, it has its own instance variables, so we could create one of those to track@flint_uses. But we'll need a method to increment this variable, perhaps something likeFireBuilder#increment_flint_uses. It doesn't make sense to add this method to the Classbackpack, because that means making it available to all classes, such asString,Float, andArray, which have nothing to do with starting fires.

We want this method to be available only to a single object, theFireBuilderclass object itself.

Fortunately, that's exactly what singleton classes are for. One of the most common use cases of singleton classes, then, is to provide class objects with methods that they can use, but don't share with other classes.

Three ways of writing so-called "class methods"

Let's get back to implicit and explicit receivers in method definitions. If you recall, Ruby assumes that there's an implicit receiver for method definitions. That is, if you don't say who the method belongs to, Ruby assumes it belongs to the current context you're in. Inside of a class definition, that's the class' "backpack" -- itsinstance_methods. But you can get around that by specifying any receiver you want for the method definition. You could set it to a class object, for example:

def FireBuilderClassObject.how_many_fires_have_been_built
  @number_of_fires
end

FireBuilderClassObject.how_many_fires_have_been_built
=> 20 # or whatever the number is at this point

Inside a class definition, the wordself means "the class object". So the above could also be written like this:

class FireBuilderClassObject
  def self.how_many_fires_have_been_built
    @number_of_fires
  end
end

and in fact, that's an extremely common way to write methods for use on the class object itself.

Finally, there's a whole special syntax for writing methods for the backpack of an object's *singleton_class:

class << my_object
  # this is my_object's singleton class definition in here
  # That means the "implicit receiver" here is my_object's *singleton_class
end

Here's how we can add our method using the specialclass << syntaxto write directly in the singleton method:

class FireBuilderClassObject
  class << self
    def how_many_fires_have_been_built
      @number_of_fires
    end
  end
end

Again, *self inside a class definition means the class object. So the above is the same as writing

class << FireBuilderClassObject
  def how_many_fires_have_been_built
    @number_of_fires
  end
end

 

but it's more common to open the singleton class inside the class definition, as in the previous example, because it keeps all of a class' business in one place.

You'll see all three of these ways of writing so-called "class methods" in Ruby. Don't be fooled, they're not doing anything other than assigning methods to the class object's singleton class.

The class object's variables

In our example above, we reference an instance variable called @number_of_firesthat should be defined on the class objectFireBuilderClassObject. That's pretty straightforward.

But in order to keep count of the fires, we have to add 1 to the@number_of_firesevery time a fire is lit.

Lighting a fire is done by the instance objects, not the class, so they need a way of accessing their class' variables inside their method definitions.

We can use the same attribute accessor methods that we use on any object to write and read its instance variables:

class FireBuilderClassObject
  def self.number_of_fires
    unless defined? @number_of_fires
      @number_of_fires = 0
    end
    @number_of_fires
  end

  def self.number_of_fires=(n)
    @number_of_fires = n
  end

  def light_a_fire
    self.class.number_of_fires = self.class.number_of_fires + 1
    "Ok it's burning. There are now #{self.class.number_of_fires} out there."
  end
end

Now, if we instantiate a number ofFireBuilderClassObjectinstances, they will correctly increment the total number of fires as they light them:

irb(main):0> builder_one = FireBuilderClassObject.new
=> #<FireBuilderClassObject:0x007fdb6802bd40>
irb(main):0> builder_two = FireBuilderClassObject.new
=> #<FireBuilderClassObject:0x007fdb6880e8c8>
irb(main):0> builder_three = FireBuilderClassObject.new
=> #<FireBuilderClassObject:0x007fdb68804558>

irb(main):0> builder_one.light_a_fire
=> "Ok it's burning. There are now 1 out there."
irb(main):0> builder_two.light_a_fire
=> "Ok it's burning. There are now 2 out there."
irb(main):0> builder_three.light_a_fire
=> "Ok it's burning. There are now 3 out there."
irb(main):0> builder_three.light_a_fire
=> "Ok it's burning. There are now 4 out there."

 

When you add a method to a specific object Ruby inserts a new anonymous class into the inheritance hierarchy as a container to hold these types of methods.

- https://www.devalot.com/articles/2008/09/ruby-singleton

 

Modules

Remember that we said Ruby provides two ways to share a set of methods with multiple classes: inheritance and composition.

We've looked at inheritance. Now let's take a look at the second way to share functionality, _composition_.

You might have noticed earlier that Class had a parent class called Module. Modules are a separate class of objects that are a lot like classes: you can define methods and variables and things on them; but while each class can only inherit from one other class (called single inheritance in computer science-speak), it can include methods from lots of modules. Modules generally don't create new objects the way classes do. They are basically buckets of behavior and logic that can be shared and passed around as needed.

In our scouts analogy, modules would be adult scouts with backpacks that didn't belong to any one troop, but that classes (the scout leaders) could decide to refer their instances to as needed.

Declaring a module is a lot like declaring a class. Just use the module keyword instead of the class keyword:

module MoreFun
  def addTwoNumbers(num1, num2)
    num1 + num2
  end
end

Instead of inheriting from modules, as classes do with other classes, classesincludethem to allow their instances to access the module's methods:

class FireBuilderClassObject
  include MoreFun
end

fire_builder = FireBuilderClassObject.new
fire_builder.addTwoNumbers(1, 2)
=> 3

Objects can also make use of a module's methods directly by using the methodextend. This effectively includes the module in the object's singleton class:

class FireBuilderClassObject
  def light_a_fire
    "it's burning now"
  end
end

fire_builder = FireBuilderClassObject.new
fire_builder.extend MoreFun
fire_builder.addTwoNumbers(1, 2)
=> 3

Remember when we looked at how to add "class methods" to a class object, by assigning them to its singleton class?

Similarly,extendis often used to add module methods to a classes "class methods", ie, its singleton class' instance methods:

class FireBuilderClassObject
  extend MoreFun

  def light_a_fire
    "it's burning now"
  end
end

FireBuilderClassObject.addTwoNumbers(1, 2)
=> 3

Again,extendis just a way toincludea module in an object's "sidekick" singleton class. In other words, building on what we learned about singleton classes and class methods, doing the above is exactly the same as doing this:

class FireBuilderClassObject
  class << self
    include MoreFun
  end

  def light_a_fire
    "it's burning now"
  end
end

FireBuilderClassObject.addTwoNumbers(1, 2)
=> 3

This might seem abstract (because it is!) but its really worthwhile as a rubyist to spend some time getting this straight. Put another way, given a module like this:

module FooModule
  def foo
    "bar"
  end
end

the following

whatever.extend FooModule

does the same as

class << whatever
  include FooModule
end

They both allow you to do

whatever.foo
=> "bar"

It just so happens that that's usually done with a class object:

class << WhateverClass
  include FooModule
end
WhateverClass.foo
=> "bar"

Examples of inheritance (parent classes) and composition (modules) in the Ruby core classes

Ruby itself uses a mix of chains of inheritance and module composition to build up the complex behaviors of its core classes that represent things like numbers, strings, hash tables, and arrays.

Just like species in the theory of evolution, Ruby's built-in classes start with the most basic — the BasicObject class — and gradually, though inheritance, build up more methods until you have objects that manage whole collections of other objects and do other complicated things.

To see how Ruby uses inheritance and composition, let's look at some built-in Ruby classes that handle the different kinds of numbers:

Bignum
Complex
Fixnum
Float
Integer
Numeric
Rational

These classes each have behaviors unique to themselves, but since they all represent some kind of number, they also all have a lot of overlapping methods.

For example, floats and integers both have a method callednonzero? 

I think you can guess what it tells you.

If you write an integer, Ruby assumes you want an object of the Integer class (or, technically, a Fixnum, which inherits from Integer):

-4.class
=> Fixnum

 

If you add a decimal place, Ruby will change the integer into a number of class Float instead:

-4.0.class
=> Float

We can see that regardless of the class, the numbers both have some of the same methods:

-4.nonzero?
=> true
-4.0.nonzero?
=> true

This shared method comes from a class calledNumericthat bothFixnumandFloatinherit from:

Float.superclass
=> Numeric
Integer.superclass
=> Numeric

FloatandIntegerreally are a kind of number (orNumeric, as the generic number class is called), so it makes sense forFloatandNumericto have an inheritance relationship to it, andNumericis where thenonzero?method lives.

There are lots of other methods useful for numbers defined on this class. Remember, you can see all the methods that a class defines for its objects, but none of the ones it inherits, by sending the class the messageinstance_methods(false)like this:

Numeric.instance_methods(false)
=> [:%, :+@, :-@, :<=>, :eql?, :singleton_method_added, :to_int, :div, :coerce, :divmod, :i, :fdiv, :modulo, :remainder, :abs, :magnitude, :real?, :integer?, :zero?, :nonzero?, :floor, :ceil, :round, :truncate, :step, :positive?, :negative?, :quo, :numerator, :denominator, :arg, :rectangular, :rect, :polar, :real, :imaginary, :imag, :abs2, :angle, :phase, :conjugate, :conj, :to_c]

If you squint and look hard at the list above you can find thenonzero?method in that list, right in the middle.

Floatalso has lots of its own methods:

Float.instance_methods(false)
=> [:%, :*, :+, :-, :/, :<, :>, :-@, :**, :<=>, :<=, :>=, :==, :===, :eql?, :inspect, :to_int, :to_s, :to_i, :to_f, :hash, :coerce, :divmod, :fdiv, :modulo, :abs, :magnitude, :zero?, :floor, :ceil, :round, :truncate, :positive?, :negative?, :quo, :nan?, :infinite?, :finite?, :next_float, :prev_float, :to_r, :numerator, :denominator, :rationalize, :arg, :angle, :phase]

Notice that some of them, like positive? andnegative?seem to overlap with the methods defined inNumeric, whichFloatinherits from. These methods are overwritten from their ancestor classes.

SoFloatinherits a number of methods fromNumeric, and overwrites some of them to make them work with the implementation details of float numbers.

As we did with theClassclass earlier in this chapter, we can see this inheritance chain by using thesuperclassmethod recursively:

Float.superclass
=> Numeric
Numeric.superclass
=> Object
Object.superclass
=> BasicObject
BasicObject.superclass
=> nil # "in the beginning..." this is the end of the inheritance chain, and the only class in all of ruby that doesn't inherit from something else. Everything in ruby descends from BasicObject.

Classes also have a convenient method called *ancestors that shows you all the sources of their inherited methods, and includes included modules as well as ancestor classes:

Float.ancestors
=> [Float, Numeric, Comparable, Object, Kernel, BasicObject]

Here we see the extra modules Comparable and Kernel that we didn't see when we called superclass on Float's ancestors just now. That's because they aren't superclasses, they're included modules:

irb(main):> Comparable.class
=> Module
irb(main):> Kernel.class
=> Module

Just as with classes, you can see the methods they supply (ie, what's in their "backpack) by calling theinstance_methodsmethod on them:

irb(main):0> Comparable.instance_methods
=> [:<, :>, :<=, :>=, :==, :between?]
irb(main):0> Kernel.instance_methods
=> [:instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :<=>, :===, :=~, :!~, :eql?, :respond_to?, :freeze, :inspect, :display, :object_id, :send, :to_s, :method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods]

Passing falseas an argument toinstance_methodsto see just the methods that are in that module or class' "backpack", we can do a neat trick with theancestorsmethod here.

If you remember theArray#eachmethod, it allows us to loop over the contents of an array and perform some operation on each element. Let's do that now to produce a list of the contents of each ancestor's backpack.

irb(main):0> Float.ancestors.each do |ancestor|
irb(main):1*   puts "#{ancestor} provides: #{ancestor.instance_methods(false)}"
irb(main):1*   puts "" # for legibility let's insert a blank line between lines of output
irb(main):1* end
Float provides: [:%, :*, :+, :-, :/, :<, :>, :-@, :**, :<=>, :<=, :>=, :==, :===, :eql?, :inspect, :to_int, :to_s, :to_i, :to_f, :hash, :coerce, :divmod, :fdiv, :modulo, :abs, :magnitude, :zero?, :floor, :ceil, :round, :truncate, :positive?, :negative?, :quo, :nan?, :infinite?, :finite?, :next_float, :prev_float, :to_r, :numerator, :denominator, :rationalize, :arg, :angle, :phase]

Numeric provides: [:%, :+@, :-@, :<=>, :eql?, :singleton_method_added, :to_int, :div, :coerce, :divmod, :i, :fdiv, :modulo, :remainder, :abs, :magnitude, :real?, :integer?, :zero?, :nonzero?, :floor, :ceil, :round, :truncate, :step, :positive?, :negative?, :quo, :numerator, :denominator, :arg, :rectangular, :rect, :polar, :real, :imaginary, :imag, :abs2, :angle, :phase, :conjugate, :conj, :to_c]

Comparable provides: [:<, :>, :<=, :>=, :==, :between?]

Object provides: []

Kernel provides: [:instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :public_method, :extend, :singleton_method, :to_enum, :enum_for, :<=>, :===, :=~, :!~, :eql?, :respond_to?, :freeze, :inspect, :display, :object_id, :send, :to_s, :method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods]

BasicObject provides: [:!, :==, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

=> [Float, Numeric, Comparable, Object, Kernel, BasicObject]

 

Conclusion: should I use modules or classes?

In general, if you are trying to decide between using a module and using class inheritance, you should go with the module.

Inheritance is a neat idea and you will hear a lot about how it mimics the evolution of species, and similar analogies. All of this is true, and it's a very useful pattern, but it also leads to complex nested dependencies.

As with everything in object-oriented programming, the guideline should be: which creates less complexity within my code? In this case, inheritance tends to create more complexity. As descendants get farther and farther away from their ancestors, it becomes harder and harder to track the effect of changes in the ancestor tree. Using theincludestatement, by contrast, provides a directly visible link to the source of the methods being included.

If your class is truly an example of the class you want to make a superclass, then it might be an appropriate case for inheritance. In the examples on theNumericclasses above, all numbers really are examples of the same thing, at least to most people, so someone (probably Yukihiro Matsumoto?) decided to use inheritance to represent that relationship.

On the other hand, lots of objects, including strings and numbers, use comparison methods like<. As we saw above,<is defined in a module calledComparable, and the number classes mix this in to use it as needed. It would lead to a tangled and abstract family tree forComparableto be a class, and have everything using<descend from it. It's just a set of behavior that can be shared across different types of objects.

To conclude, there are no real disadvantages to using modules instead of classes to share code, so feel free to use modules liberally. On the other hand, since you can only inherit once, you better inherit well. 

Example of certificate of achievement
Example of certificate of achievement