CSC/ECE 517 Fall 2010/ch2 4d RB

From Expertiza_Wiki
Jump to navigation Jump to search

Introduction

Namespaces are used in Computer Science to group similar items into different logical units, so that one item can be un-ambigously differentiated from another item. Trivial it may seem, but creating namespaces is one of the most basic activities of modern day programming. It makes a program more organized and less prone to errors. We'll start with some basic features of namespaces and then we'll proceed to uses of namespaces in various languages. We'll also answer this question that why namespaces make our programs more manageable and less complex. At last we'll look into some advanced concepts like namespaces in XML.

Why namespaces

The Problem

In general programming languages like C++, variable names, function names, structure names, class names, union names and enumerations fall under one general category called names. While writing big programs involving several programmers, the situation is likely to go out of hand if proper control is not exercised on the visibility of these names.1 For example, lets consider the following:


//library1.h
char hello();
void print();
class EmpSal
{
  char* ename;
  int esal;
}
// library2.h
char hi();
void print();
class EmpSal
{
  char* nm;
  float tax;
}

In the above examples, we have two header files, library1.h and library2.h which have the function void print() and class EmpSal. Now if both the header files are included in a program (see below) and a reference to the class is made, or the function is called, then this situation becomes ambiguous.

//prog.c
#include "library1.h"
#include "library2.h"
void main()
{
 print();   // ambiguous call
 EmpSal es = new EmpSal(); // ambiguous reference EmpSal a class
}

We can see in the above code that a call to the method print() and creation of the object EmpSal es is ambigous. Since both the header files contain this method and this class, the compiler won't know which library is being referred here. In such a case, the compiler flashes an error message of name clash.

Possible solutions to this problem

The first solution can be to modify the name of the method and the class in one of the libraries. This will prevent a name clash and the code will compile correctly. But this is not a feasible solution. It might be a case, where the library is being referred in other parts of the program which we don't have access to. So making changes in the library will cause problems in other parts of the program. Secondly, the libraries may be "read-only" and we may not be allowed to change any part of the library. 7Thirdly, even if are able to make changes in the library and make our code run, this is not the best approach as this requires a lot of re-work and it may lead to potential bugs in the program.8

The second, more appropriate approach can be to use the concept of namespaces and the libraries can be placed into specific namespaces. C++ by default provides a global namespace where all the class objects and methods are placed. The global namespaces can be split into further manageable pieces using the namespaces features in C++, Java, Python etc.

Lets take up an example of namespaces in C++ to understand this concept.

 //library1.h
namespace Library1
char hello();
void print();
class EmpSal
{
  char* ename;
  int esal;
}
// library2.h
namespace Library2
char hi();
void print();
class EmpSal
{
  char* nm;
  float tax;
}
using namespace std;
void main()
{
 Library1::print();
 Library2::printf();
 
 Library1::EmpSal es1;
 Library2::EmpSal es2;
}

In the above example, both the libraries are placed into different namespaces. This removes the ambiguity in the function calls. Each function can be referred uniquely using its namespace preceding it. Different methods sharing the same name can be present in different namespaces and can be referred to with any conflict. As long as the names are in different namespaces, each name will be unique because of the addition of the namespace identifier.

Namespaces in different languages

C++

Namespaces are used in C++ using the keyword namespace. This keyword can be used to specify a new namespace as well as can be used to access an existing namespace.

Specifying a new namespace:

namespace abc;
void display()
{
 cout<<"Hello Namespaces";
}

Accessing the function using the namespace:

using namespace abc;
display();

Java

The concept of namespaces is implemented in Java using modules. Java has a system of packages and sub-packages and each package contains properties and methods. In order to access the contents of a package, the keyword import is used. Lets look at an example to make things clear.

Creating a new module:

module java.Parentpack.childpack;
void display1();
void display2();

Accessing this module:

import java.Parentpack.childpack;
display1();
display2();

Ruby

Ruby has the concept of modules which can contain various methods. The modules can then be accessed using the require directive. Lets look at an example to look how modules are implemented in Ruby.

Creating a new module:

module module1
def display1
{
  puts "Hello modules"
}
end

Accessing the module:

require module1
display1

Facts about namespaces

Here are some facts about Namespace relevant to C++:

1. The syntax of namespace is similar to that of the class except for the semicolon beyond the closing brace.

2. Declarations that are not present in any namespace are by default in the global namespace.

3. A definition of namespace can span over multiple header files. Refer the example below for more details:

// header1.h
namespace mynmspace
{
 void print();
}
//header2.h
namespace mynmspace
{
 void display();
}

This style of namespace spanning is called extension namespace definition.

4. In C++ we can give alternative names to namespaces which is called namespace alias.4 This feature is especially useful in cases where the namespace name is in-conveniently long.

namespace managers_and_directors
{
 void print_manager_salary();
 void print_director_salary();
}
namespace mad = managers_and_directors;

5. The global namespace name can not be same as any other global entity name in the entire program.

6. The members of any namespace can even be defined outside the namespace. 5 Lets see the example below to make it more clear.

namespace sample
{
 void display();
}
void sample::display()
{
 cout<<"\nDefining function outside the namespace";
}

7. The definition of a namespace should only appear in the global scope. Lets look at an example that shall cause an error.

void main()
{
 namespace myspace
 {
   // this will generate compilation error
 }
}

8. The namespace definition can be nested within one another. Lets look at an example.

namespace outerspace
{
 void display();
 namespace innerspace
 {
  void innerdisplay();
 }
}

Using a namespace in C++

There are two techniques using which a namespace can be accessed in C++. These two techniques are: 1. Through scope resolution operator 2. Through using keyword

Lets look at the examples of each technique:

Accessing namespace through Scope Resolution Operator

We can access variables and methods of a namespace by mentioning the name of the namespace followed by scope resolution operator followed by the method or variable name. Lets look at an example.

Accessing namespace through using keyword

The second way to use namespaces is to use using keyword instead of using the scope resolution operator before very name.2 Using operator allows us to import the entire namespace at a single time.

Let us look at an example to discover how using keyword can be used.

namespace samplespace
{
 void display()
 {
   cout<<"Hello namespaces";
 }
}
void main()
{
  using namespace samplespace;
  display();
}

As we can see in the above example, the using keyword is used to import the entire namespace and then the function can be called without the need of scope resolution operator.

Contrast between Score Resolution and keyword using

As discussed earlier, the namespaces can be referred in C++ through scope resolution operator or through using operator. Each approach has its own advantages and disadvantages. Lets discuss both the approaches and the trade-offs between them -

Scope Resolution

1. This approach is useful if we are going to refer methods and properties of different types repeatedly in our program. So instead of re-importing the entire namespace again and again, it is better to refer to a method or a property of a specific namespace.

2. This technique is faster because the entire namespace need not be loaded.

3. However this technique becomes tedious, because we need to prefix the name of the namespace before every method call and property use.

This technique is best for the scenario where multiple methods of multiple namespaces needs to be referred randomly in a code.

Using keyword

1. This approach is useful in the scenario where the most of the methods of a specific namespace needs to be referred in a code repeatedly.

2. No need to mention the name of the namespace again and again.

3. In order to switch to a different namespace, use the using keyword again and specify the new namespace.

4. At a given time, only one namespace can remain active.

This technique is best for the scenarios where multiple methods and properties of a namespace needs to be referred repeatedly.

Namespaces in XML

XML namespaces provide a simple technique for uniquely identifying elements and attribute names which are referenced in XML documents. This is achieved by associating a particular tag set by associating a prefix with a URI reference.4 Another goal of XML namespaces is to provide a mechanism for authoring compound documents (documents consisting of elements and attributes from multiple DTDs or schemas) in such a way that will provide global identification without namespace collisions.6 Lets look at an example to make this concept more clear.

 <h:html xmlns:nm1="http://www.abc.com/link1"
       xmlns:nm2="http://www.xyz.com/link2">
  <nm1:head><nm1:title>Salary review</nm1:title></nm1:head>
  <nm1:body>
   <nm2:bookreview>
   <nm2:title>XML: A Primer</nm2:title>
   </nm2:bookreview>
  </nm1:body>
 </nm1:html>

We can observe in the above example that teo namespaces have been used for XML tags.

Namespace 1: nm1 (refers to: http://www.abc.com/link1) Namespace 2: nm2 (refers to: http://www.xyz.com/link2)

These namespaces can be used to uniquely identify elements having the same tag name in an XML document. nm1 and nm2 are the shorthand notations of the entire XML namespace names.

Conclusion

In this wiki-chapter we discussed the definition of namespaces followed by its uses in various aspects of programming. We discussed how the create a new namespace and then how to use it in different programming languages. We then followed up on various properties of namespaces and at the end discussed on its usage in XML. Usage of namespaces improves the modularity of the software and also helps in its maintenence, which eventually leads to a robust code development.

References

  1. Peachpit - Introduction to Object Oriented Programming - Namespaces & Scope Resolution
  2. Objectmix Namespace and/or scope resolution? : c++
  3. Visual C# namespaces forums
  4. W3Schools - XML Namespaces
  5. Manual Namespaces
  6. Namespaces and XSLT Stylesheets XML.com
  7. Uniform Resource Names (URN) Namespaces IANA.org
  8. Notes on Name Spaces for R