Initializing Instance Variables Defined by a Module

Credit: Phil Tomson

Problem

You have a mixin module that defines some instance variables. Given a class that mixes in the module, you want to initialize the instance variables whenever an instance of the class is created.

Solution

Define an initialize method in the module, and call super in your class's constructor. Here's a Timeable module that tracks when objects are created and how old they are:

	module Timeable
	 attr_reader :time_created

	 def initialize
	 @time_created = Time.now
	 end

	 def age #in seconds
	 Time.now - @time_created
	 end
	end

Timeable has an instance variable time_created, and an initialize method that assigns Time.now (the current time) to the instance variable. Now let's mix Timeable into another class that also defines an initialize method:

	class Character
	 include Timeable
	 attr_reader :name
	 def initialize( name )
	 @name = name
	 super() #calls Timeable's initialize
	 end
	end
	c = Character.new "Fred"

	c.time_created
	# => Mon Mar 27 18:34:31 EST 2006

 

Discussion

You can define and access instance variables within a module's instance methods, but you can't actually instantiate a module. A module's instance variables only exist within objects of a class that includes the module. However, classes don't usually need to know about the instance variables defined by the modules they include. That sort of information should be initialized and maintained by the module itself.

The Character#initialize method overrides the Timeable#initialize method, but you can use super to call the Timeable constructor from within the Character constructor. When a module is included in a class, that module becomes an ancestor of the class. We can test this in the context of the example above by calling the Module#ancestors on the Character class:

	Character.ancestors # => [Character, Timeable, Object, Kernel] 

When you call super from within a method (such as initialize), Ruby finds every ancestor that defines a method with the same name, and calls it too.

See Also

  • Recipe 8.13, "Calling a Superclass's Method"
  • Sometimes an initialize method won't work; see Recipe 9.3, "Mixing in Class Methods," for when it won't work, and how to manage without one
  • Recipe 9.9, "Automatically Initializing Mixed-In Modules," covers an even more complex case, when you want a module to perform some initialization, without making the class that includes do anything at all beyond the initial include


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net