Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Ruby Programming
Previous Page Home Next Page

Instance Variables in Mixins

People coming to Ruby from C++ often ask us, ``What happens to instance variables in a mixin? In C++, I have to jump through some hoops to control how variables are shared in a multiple-inheritance hierarchy. How does Ruby handle this?''

Well, for starters, it's not really a fair question, we tell them. Remember how instance variables work in Ruby: the first mention of an ``@''-prefixed variable creates the instance variable in the current object, self.

For a mixin, this means that the module that you mix into your client class (the mixee?) may create instance variables in the client object and may use attr and friends to define accessors for these instance variables. For instance:

module Notes
  attr  :concertA
  def tuning(amt)
    @concertA = 440.0 + amt
  end
end

class Trumpet   include Notes   def initialize(tune)     tuning(tune)     puts "Instance method returns #{concertA}"     puts "Instance variable is #{@concertA}"   end end

# The piano is a little flat, so we'll match it Trumpet.new(-5.3)
produces:
Instance method returns 434.7
Instance variable is 434.7

Not only do we have access to the methods defined in the mixin, but we get access to the necessary instance variables as well. There's a risk here, of course, that different mixins may use an instance variable with the same name and create a collision:

module MajorScales
  def majorNum
    @numNotes = 7 if @numNotes.nil?
    @numNotes # Return 7
  end
end

module PentatonicScales   def pentaNum     @numNotes = 5 if @numNotes.nil?     @numNotes # Return 5?   end end

class ScaleDemo   include MajorScales   include PentatonicScales   def initialize     puts majorNum # Should be 7     puts pentaNum # Should be 5   end end

ScaleDemo.new
produces:
7
7

The two bits of code that we mix in both use an instance variable named @numNotes. Unfortunately, the result is probably not what the author intended.

For the most part, mixin modules don't try to carry their own instance data around---they use accessors to retrieve data from the client object. But if you need to create a mixin that has to have its own state, ensure that the instance variables have unique names to distinguish them from any other mixins in the system (perhaps by using the module's name as part of the variable name).
Ruby Programming
Previous Page Home Next Page

 
 
  Published under the terms of the Open Publication License Design by Interspire