The Working Programmer's Guide To Variables - Scope, Lifetime And More
Written by Harry Fairhead   
Article Index
The Working Programmer's Guide To Variables - Scope, Lifetime And More
Objects And Lifetimes
Existence

Objects and Namespaces

However you shouldn't write off the idea of the global variable because it has new life in the form of object oriented programming.

In this paradigm the objects are the fundamental modular division used to divide a program up into manageable chunks. Each object keeps its variables local and even private i.e. inaccessible from outside of the code that makes up the object however in many designs the main objects themselves have what are effectively global names. 

 

Banner

 

This is the reason we have had to introduce the idea of namespaces.

A name is now promoted to something much more involved. Now you can assign a very long and complicated name which you hope will not collide with other similar names.

For example:

mycompany.myproject.myframework.myclass1

might be the name of a class that you would otherwise have just named myclass1.

Obviously there is a lot less chance of collision if you use the long name than if you use the short name - but the long name is a bit of a nuisance to type.

The solution is the introduction of a namespace - basically a default prefix added to all variables. That is if you are working in the namespace:

mycompany.myproject.myframework

then when you use the name myclass1 it is assumed you mean:

mycompany.myproject.myframework.myclass1

Of course if you want to use myclass1 in a different name space then you can do so but only if you enter the complete qualified name of the class you really want to use. For example:

anothercompany.myproject.myclass1

is a different class from the one you created.

To make things easier various looser name space rules are generally used. For example, if you use an unqualified name then each name space is searched until a fully qualified name (FQN) is found. If more than one FQN is found that matches then the collision is brought to the programmer's notice and a fully or partly qualified name has to be used to resolve the ambiguity.

Put simply name spaces were introduced to control global names.

You may have noticed that this entire discussion has been in terms of class rather than object. The same ideas apply, however, to objects, i.e. instances of classes.

Your project has a name space associated with it and when you create a new object it too has a fully qualified name given by appending the name space. Of course it's up to you to keep everything under control and avoid name collisions within your own small naming universe.

Name spaces aren't perfect but they are the only way we have of keeping global names under control.

variablescope

Block scope

After considering the elevated topic of objects and namespaces let's return to the nitty gritty of variables and their scope.

You might think that local or global variables were the only two possibilities but there is another.

If the language that you are using has a block structure, and most modern languages do, then you can use the block structure to determine the scope.

The most extreme form of block structure is where a function can have functions defined within it and they can have functions defined with in them and so on. This is a form of nesting of one function inside another that most object oriented languages have given up - it isn't particularly useful when you have the range of organisational schemes that objects give you. However, even object oriented languages allow you to nest the definition of a class within another class and even allow nested blocks of code within a method or function.

What all this comes down to is that most languages recognise a nested organization of code into blocks of various sorts inside blocks. 

If you do write programs using block structure then an easy to implement and understand scope rule is that a variable is defined in any blocks contained within the block that the variable is declared in.

This produces a sort of halfway between a local and a global variable. The variable is local to all blocks that are defined outside of the block that the variable is declared in but effectively global to all blocks defined within the block that declares the variable.

You can also think of local and global variables as being special cases of the nested scope rule. Global variables are simply variables declared in a block that contains every other block and local variables are declared in a block that contains only the procedure that they are local to.

For example, consider the following short extract:

private void MyMethod(){
 {
  int i = 1;
  {
   i = 2;
  }
 }
}

The use of code blocks within a method is so rare that you might not even recognise this as valid code - it's C# and it is valid.

There are two code blocks defined within the method. The variable i is declared in the first block and its scope is the first block and all blocks that it contains. Thus the assignment in the inner second block is valid and it assigns 2 to the variable i declared in the outer block. Notice that the method doesn't have a variable called i defined in its "top level" scope. That is you try to use a variable called i within the method i.e. outside of the block it is declared in then an error results.

Now consider the following:

{
 int i = 1;
 {
  i = 2;
 }
}
{
 int i = 4;
}

This too is perfectly valid in C#.  The variable i declared in the final block is only in scope within its block and it doesn't interfere or clash with the i defined in the first block.

When you are first learning any block structured language the scope rules seem a bit complicated and so there is a tendency to not make use of them and concentrate on learning the language. After a while you end up all but forgetting them, with only the occasional memory jog from reading the bit in the manual every time a new version of the language appears.

However, from a more sophisticated point of view the way that the scope rule works is very clever and very close to the way that you actually want to work most of the time. It also it a bit like an inheritance mechanism for data, each inner block inheriting all of the outer blocks variables and procedures.

Visibility

The final twist to the story is visibility.

Suppose a variable is in scope but you then declare another variable of the same name in an inner block. Presumably you would like to work with the newly declared variable and not the one defined in the outer block.

The outer block's version of the variable is said to be in scope but inaccessible or not visible and the new definition replaces it.

You can invent additional rules to make variables that are in scope but redefined visible. For example, you could insist that every block was named and then you could refer to a variable as blockname.variablename. If you leave off the blockname then it defaults to the current block.

If this sounds familiar then I am not surprised because it is exactly the mechanism that object oriented languages used for making clear which object method is to be used in an object hierarchy.

However, this said, many language designers have decided that such a name collision is not a good idea and will flag any attempt to declare a variable within an inner block that is already in scope as an error. For example, in C# the following is an error:

{
 int i = 1;
 {

  int i = 2;

 }
}

 

Banner

 

<ASIN:0201350882>

<ASIN:0201657880>

<ASIN:0321637135>

<ASIN:0521614104>



 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.