Avoiding Naming Collisions with Namespaces

Problem

You want to define a class or module whose name conflicts with an existing class or module, or you want to prevent someone else from coming along later and defining a class whose name conflicts with yours.

Solution

A Ruby module can contain classes and other modules, which means you can use it as a namespace.

Here's some code from a physics library that defines a class called String within the StringTheory module. The real name of this class is its fully-qualified name: StringTheory::String. It's a totally different class from Ruby's built-in String class.

	module StringTheory
	 class String
	 def initialize(length=10**-33)
	 @length = length
	 end
	 end
	end

	String.new # => ""

	StringTheory::String.new
	# => #

 

Discussion

If you've read Recipe 8.17, you've already seen namespaces in action. The constants defined in a module are qualified with the module's name. This lets Math::PI have a different value from Greek::PI.

You can qualify the name of any Ruby object this way: a variable, a class, or even another module. Namespaces let you organize your libraries, and make it possible for them to coexist alongside others.

Ruby's standard library uses namespaces heavily as an organizing principle. An excellent example is REXML, the standard XML library. It defines a REXML namespace that includes lots of XML-related classes like REXML::Comment and REXML::Instruction. Naming those classes Comment and Instruction would be a disaster: they'd get overwritten by other librarys' Comment and Instruction classes. Since nothing about the genericsounding names relates them to the REXML library, you might look at someone else's code for a long time before realizing that the Comment objects have to do with XML.

Namespaces can be nested: see for instance rexml's REXML::Parsers module, which contains classes like REXML::Parsers::StreamParser. Namespaces group similar classes in one place so you can find what you're looking for; nested namespaces do the same for namespaces.

In Ruby, you should name your top-level module after your software project (SAX), or after the task it performs (XML::Parser). If you're writing Yet Another implementation of something that already exists, you should make sure your namespace includes your project name (XML::Parser::SAX). This is in contrast to Java's namespaces: they exist in its package structure, which follows a naming convention that includes a domain name, like org.xml.sax.

All code within a module is implicitly qualified with the name of the module. This can cause problems for a module like StringTheory, if it needs to use Ruby's built-in String class for something. This should be fixed in Ruby 2.0, but you can also fix it by setting the built-in String class to a variable before defining your StringTheory::String class. Here's a version of the StringTheory module that can use Ruby's builtin String class:

	module StringTheory2
	 RubyString = String
	 class String
	 def initialize(length=10**-33)
	 @length = length
	 end
	 end

	 RubyString.new("This is a built-in string, not a StringTheory2::String")
	end
	# => "This is a built-in string, not a StringTheory2::String"

 

See Also

  • qRecipe 8.17, "Declaring Constants"
  • Recipe 9.7, "Including Namespaces"


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