Modules
Ref. WGR Chapter 4, Modules and program organization
Modules and Mixins
- Any class (or object) can include a Module
- also known as mixing in
- so Modules are also called Mixins
- Modules provide behavior but no state
- more precisely, they affect the extending object's state
Multiple modules
- You can mix in as many modules as you like
- Resembles multiple inheritance, but less confusing
Module definition
@@@ ruby
module Greeter
def greet
puts "Hello!"
end
end
Module usage
@@@ ruby
class Person
include Greeter
end
alice = Person.new
alice.greet
Modules cannot be instantiated
Greeter.new #=> undefined method `new' for Greeter:Module
Modules have no state
but they can fake it pretty well
@@@ ruby
module Stacky
def stack
@stack ||= []
end
def push obj
stack.push obj
end
def pop
stack.pop
end
end
@stack
will become an instance variable on the includer
load
vs. require
vs. include
vs. extend
- They all sound so similar!
- load inserts a file's contents
load 'config.rb'
- The same file can be
load
ed more than once, last one sticks
- require inserts a file's parsed contents
require 'config'
require
ing the same file more than once has no effect, first one sticks
- include mixes in a module into this class' instances
include Config
- extend mixes in a module into
self
, usually to add class methodsextend Config
module lookup gotchas
- If a class defines the same method as a module, then the class wins, even if the module was included later
- If two modules define the same method, then the last one to be included wins
If you include a module twice, then the second inclusion is ignored, so it's still further back on the lookup chain
@@@ ruby class Foo include A include B include A #<< ignored! end
Using Modules for Organization
- Modules are used as namespaces
- Classes are also modules
class Class < Module
Module Organization Example
whiz.rb
:
@@@ ruby
module Whiz
VERSION = "1.0.2"
class GeeGaw
# ...
end
end
whiz/bang.rb
:
@@@ ruby
module Whiz
class Bang
def geegaw
# inside the module, its members are in scope
@geegaw ||= GeeGaw.new
end
end
end
client.rb
:
@@@ ruby
require "whiz"
require "whiz/bang"
# outside the module, its members are not in scope
# you need to name it explicitly
puts Whiz::VERSION
bang = Whiz::Bang.new