Relationships of Class, Module, and Object

  • vertical arrows represent inheritance
  • parentheses represent meta-classes
  • all metaclasses are instances of the class Class
    
                              +------------------+
                              |                  |
                Object---->(Object)              |
                 ^  ^        ^  ^                |
                 |  |        |  |                |
                 |  |  +-----+  +---------+      |
                 |  |  |                  |      |
                 |  +-----------+         |      |
                 |     |        |         |      |
          +------+     |     Module--->(Module)  |
          |            |        ^         ^      |
     OtherClass-->(OtherClass)  |         |      |
                                |         |      |
                              Class---->(Class)  |
                                ^                |
                                |                |
                                +----------------+

Module

  • Module Doc
  • Taxonomy of Rails Plugins
  • Module is collection of methods and constants.
  • Methods in a module may be instance methods or module methods.
  • Instance methods appear as (instance) methods in a class when the module is included, module methods don't.
  • Module methods may be called without creating an encapsulating object, instance methods may not.
  module Mod
    include Math
    CONST = 1
    def meth
      #  ...
    end
  end
  Mod.class              #=> Module
  Mod.constants          #=> ["E", "PI", "CONST"]
  Mod.instance_methods   #=> ["meth"]

Mod.included( other_mod )

Callback invoked whenever the receiver is included in another module or class.

  module A
    def A.included(mod)
      puts "#{self} included in #{mod}"
    end
  end

  module Enumerable; include A; end  # => "A included in Enumerable"

A common Ruby idiom for using mod.included:

  • Type: "mod"-tab in Textmate, and select option 3 to generate the following template
  module FooBar
    module ClassMethods
      def foo; puts "class method: foo()"; end
      def bar; puts "class method: bar()"; end
    end

    module InstanceMethods
      def foo; puts "instance method: foo()"; end
      def bar; puts "instance method: bar()"; end
    end

    def self.included(receiver)
      receiver.extend         ClassMethods
      receiver.send :include, InstanceMethods
    end
  end

  class A; include FooBar; end
  A.foo       # => class method: foo()
  A.bar       # => class method: bar()
  A.new.foo   # => instance method: foo()
  A.new.bar   # => instance method: bar()

An example for adding associations to ActiveRecord.

  module TasksAssociation
    def task_names
      tasks.map(&:name)
    end

    def self.included(klass)
      klass.has_many_and_belongs_to :tasks
    end
  end

  class Todo < ActiveRecord::Base
    include TasksAssociation  # gain todo.tasks and todo.task_names
  end

Mod.extend

You can use extend self trick to turn all instances methods into class methods of the module:

  module A
    extend self  # all instances methods now become class methods
    def foo; 'foo'; end
    def bar; 'bar'; end
  end

  A.foo  # => 'foo'
  A.bar  # => 'bar'

Class

  • Class Doc
  • Ruby classes are first-class objects: each is an instance of class Class.
  • New class is created by instantiating a new object of type Class. The object is assigned to a global constant (the Name of the class).
  • When Name.new is called, the new (instance) method in Class is run by default.

Class.inherited

class.inherited is a callback that gets invoked whenever a subclass of the current class is created.

  class Foo
    def self.inherited(subclass)
       puts "New subclass: #{subclass}"
    end
  end

  class Bar < Foo; end    # outputs => New subclass: Bar
  class Baz < Bar; end    # outputs => New subclass: Baz (class method is "inherited" as well)

Class.superclass

Returns the superclass of class, or nil

  File.superclass     #=> IO
  IO.superclass       #=> Object
  Object.superclass   #=> nil