Está en la página 1de 13

Accesibilidad y mbito

Tal y como comentamos anteriormente, dependiendo de dnde y cmo estn declarados los tipos de datos y los miembros definidos en ellos, tendremos o no acceso a esos elementos. Recordemos que el mbito es el alcance con el que podemos acceder a un elemento y depende de dnde est declarado; por otro lado, la accesibilidad depende de cmo declaremos cada uno de esos elementos.

mbito
Dependiendo de donde declaremos un miembro o un tipo, ste tendr mayor alcance o cobertura, o lo que es lo mismo, dependiendo del mbito en el que usemos un elemento, podremos acceder a l desde otros puntos de nuestro cdigo. A continuacin veremos con detalle los mbitos en los que podemos declarar los distintos elementos de Visual C# 2005. mbito de bloque: Disponible nicamente en el bloque de cdigo en el que se ha declarado. Por ejemplo, si declaramos una variable dentro de un bucle for o un if, esa variable solo estar accesible dentro de ese bloque de cdigo. mbito de procedimiento: Disponible nicamente dentro del procedimiento en el que se ha declarado. Cualquier variable declarada dentro de un procedimiento (mtodo o propiedad) solo estar accesible en ese procedimiento y en cualquiera de los bloques internos a ese procedimiento. mbito de mdulo: Disponible en todo el cdigo de la clase o la estructura donde se ha declarado. Las variables con mbito a nivel de mdulo, tambin estarn disponibles en los procedimientos declarados en el mdulo (clase o estructura) y por extensin a cualquier bloque dentro de cada procedimiento. mbito de espacio de nombres: Disponible en todo el cdigo del espacio de nombres. Este es el nivel mayor de cobertura o alcance, aunque en este nivel solo podemos declarar tipos como clases, estructuras y enumeraciones, ya que los procedimientos solamente se pueden declarar dentro de un tipo.

Nota: Por regla general, cuando declaramos una variable en un mbito, dicha variable "ocultar" a otra que tenga el mismo nombre y est definida en un bloque con mayor alcance, aunque veremos que en C# existen ciertas restricciones dependiendo de dnde declaremos esas variables.

En VB6 los mbitos disponibles solamente eran los de mdulo y procedimiento, en estos casos, cualquier variable declarada en un procedimiento oculta a una

definida en un mdulo. En Visual C# 2005 podemos definir una variable dentro de un bloque de cdigo, en ese caso dicha variable solo ser accesible dentro de ese bloque. Aunque, como veremos a continuacin, en un procedimiento solamente podremos definir variables que no se oculten entre s, estn o no dentro de un bloque de cdigo.

mbito de bloque
En los siguientes ejemplos veremos cmo podemos definir variables para usar solamente en el bloque en el que estn definidas. Los bloques de cdigo en los que podemos declarar variables son los bucles, (for,foreach, do, while), y los bloques condicionales, (if, switch), o en cualquier otro bloque formado por un par de llaves. Por ejemplo, dentro de un procedimiento podemos tener varios de estos bloques y por tanto podemos definir variables "internas" a esos bloques:
int n = 3; // for(int i = 1; i <= 10; i++ ) { int j = 0; j += 1; if( j < n ) { //... } } // if( n < 5 ) { int j = n * 3; } // do { int j = 0;

for(int i = 1; i <= n; i++) { j += i; } if( j > 10 ) break; }while(true);

La variable n estar disponible en todo el procedimiento, por tanto podemos acceder a ella desde cualquiera de los bloques. En el primer bucle for, definimos la variable i como la variable a usar de contador, esta variable solamente estar accesible dentro de este bucle for. Lo mismo ocurre con la variable j. En el primer if definimos otra variable j, pero esa solo ser accesible dentro de este bloque y por tanto no tiene ninguna relacin con la definida en el bucle for anterior. En el bucle do volvemos a definir nuevamente una variable j, a esa variable la podemos acceder solo desde el propio bucle do y cualquier otro bloque de cdigo interno, como es el caso del bucle for, en el que nuevamente declaramos una variable llamada i, que nada tiene que ver con el resto de variables declaradas con el mismo nombre en los otros bloques.

Nota: El cdigo del bucle do mostrado anteriormente se convertir en un bucle infinito, ya que la variable j siempre se pone a cero en cada repeticin del bucle do/while, por tanto solo hay que tomarlo como un ejemplo para probar lo del mbito de las variables.

Lo nico que no podemos hacer en cualquiera de esos bloques, es declarar una variable llamada n, ya que al estar declarada en el procedimiento, el compilador de C# nos indicar que no podemos ocultar una variable previamente definida fuera del bloque, tal como podemos ver en la figura 2.5.

Figura 2.5. Error al ocultar una variable definida en un procedimiento Esta restriccin solo es aplicable a las variables declaradas en el procedimiento, ya que si declaramos una variable a nivel de mdulo, no habr ningn problema para usarla dentro de un bloque, esto es as porque en un procedimiento podemos declarar variables que se llamen de la misma forma que las declaradas a nivel de mdulo, aunque stas ocultarn a las del "nivel" superior.

mbito de procedimiento
Las variables declaradas en un procedimiento tendrn un mbito o cobertura que ser el procedimiento en el que est declaradas, y como hemos visto, ese mbito incluye tambin cualquier bloque de cdigo declarado dentro del procedimiento. Estas variables ocultarn a las que se hayan declarado fuera del procedimiento, si bien, dependiendo del tipo de mdulo, podremos acceder a esas variables "externas" indicando el nombre completo del mdulo o bien usando la instruccin this seguida del nombre de la variable. Pero mejor vemoslo con un ejemplo. En el siguiente cdigo, definimos una clase en la que tenemos un campo llamado Nombre, tambin definimos un mtodo en el que internamente se utiliza una variable llamada Nombre, para acceder a la variable declarada en la clase, tendremos que usar la instruccin o palabra clave this.
public class Cliente { public string Nombre = "Juan"; public string Mostrar() { string Nombre = "Pepita"; return "Externo= " + this.Nombre + ", interno= " + Nombre;

} }

mbito de mdulo
Cuando hablamos de mdulos, nos estamos refiriendo a una clase, a una estructura o a cualquier otro tipo de datos que nos permita .NET. En estos casos, las variables declaradas dentro de un tipo de datos sern visibles desde cualquier parte de ese tipo, siempre teniendo en cuenta las restricciones mencionadas en los casos anteriores.

mbito de espacio de nombres


Los espacios de nombres son los contenedores de tipos de datos de mayor nivel, y sirven para contener definiciones de clases, estructuras, enumeraciones y delegados. Cualquier tipo definido a nivel de espacio de nombres estar disponible para cualquier otro elemento definido en el mismo espacio de nombres. Al igual que ocurre en el resto de mbitos "inferiores", si definimos un tipo en un espacio de nombres, podemos usar ese mismo nombre para nombrar a un procedimiento o a una variable, en cada caso se aplicar el mbito correspondiente y, tal como vimos anteriormente, tendremos que usar nombres nicos para poder acceder a los nombres definidos en niveles diferentes.

La palabra clave global::


En Visual C# 2005 podemos definir espacios de nombres cuyos nombres sean los mismos que los definidos en el propio .NET Framework, para evitar conflictos de mbitos, podemos usar la palabra clave global:: para acceder a los que se han definido de forma "global" en .NET. Por ejemplo, si tenemos el siguiente cdigo, declarado dentro del espacio de nombres que C# define en cada nuevo proyecto, en el que definimos una clase dentro de un espacio de nombres llamado System y queremos acceder a uno de los tipos definidos en el espacio de nombres System de .NET, tendremos un problema:
namespace System { class Cliente { public string Nombre; public System.Int32 Edad;

} }

El problema es que el compilador de C# nos indicar que el tipo Int32 no est definido, ya que intentar buscarlo dentro del mbito que actualmente tiene, es decir, la declaracin que nosotros hemos hecho de System, por tanto para poder acceder al tipo Int32 definido en el espacio de nombres "global" System de .NET, tal como podemos ver en la figura 2.6, para solventar el problema, tendremos que usar la instruccin global:: delante del espacio de nombre que produce el error.

Figura 2.6. Error por conflicto de espacios de nombres globales

El cdigo, una vez solventado el error, quedara de la siguiente forma:


namespace System { class Cliente { public string Nombre; public global::System.Int32 Edad;

public override string ToString() { return "Nombre= " + Nombre + ", edad= " + Edad; } } }

Por supuesto nuestro espacio de nombres System nos dar ms quebraderos de cabeza, ya que al usarlo desde el mtodo Main de la clase principal de nuestro proyecto, nos obligar a usar el "nombre real" o completo de la clase Cliente, y si nuestra intencin es usar la clase Console para mostrar el nombre y la edad, tambin tendremos que aplicarle el modificador global:: a esa clase, para que el compilador sepa dnde encontrarla.
class Program { static void Main(string[] args) { System.Cliente cli = new System.Cliente(); cli.Nombre = "Pepe"; cli.Edad = 22; global::System.Console.WriteLine(cli); } }

Como podemos comprobar, el uso del nombre System como un espacio de nombres interno de nuestro proyecto no es una buena eleccin, aunque aqu lo hemos usado para resaltar los conflictos que se pueden producir al usar identificadores de espacios de nombres que ya estn definidos en la biblioteca de clases de .NET Framework.

Nota: Afortunadamente este conflicto con los espacios de nombres no ser muy habitual para los desarrolladores que usemos el idioma de Cervantes, por la sencilla razn de que los espacios de nombres de .NET Framework suelen estar definidos usando palabras en ingls.

Accesibilidad
La accesibilidad es la caracterstica que podemos aplicar a cualquiera de los elementos que definamos en nuestro cdigo. Dependiendo de la accesibilidad declarada tendremos distintos tipos de accesos a esos elementos. Los modificadores de accesibilidad que podemos aplicar a los tipos y elementos definidos en nuestro cdigo pueden ser cualquiera de los mostrados en la siguiente lista:

public: Acceso no restringido. Este es modificador de accesibilidad con mayor "cobertura", podemos acceder a cualquier miembro pblico desde cualquier parte de nuestro cdigo. Aunque, como veremos, este acceso no restringido puede verse reducido dependiendo de dnde lo usemos. protected: Acceso limitado a la clase contenedora o a los tipos derivados de esta clase. Este modificador solamente se usa con clases que se deriven de otras. internal: Acceso limitado al proyecto actual (o ensamblado). protected internal: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora. Una mezcla de los dos modificadores anteriores. private: Acceso limitado al tipo contenedor. Es el ms restrictivos de todos los modificadores de accesibilidad.

Estos modificadores de accesibilidad los podemos usar tanto en clases, estructuras, interfaces, enumeraciones, delegados, eventos, mtodos, propiedades y campos. Aunque no sern aplicables en espacios de nombres (Namespace) ni en los miembros de las interfaces y enumeraciones.

Accesibilidad de las variables en los procedimientos


Las variables declaradas dentro de un procedimiento solo son accesibles dentro de ese procedimiento, en este caso solo se puede aplicar el mbito privado, aunque no podremos usar la instruccin private, sino declararlas de la forma habitual.

Las accesibilidades predeterminadas


La accesibilidad de un tipo, variable o procedimiento en la que no hemos indicado el modificador de accesibilidad depender del sitio en el que lo hemos declarado. Por ejemplo, las clases y estructuras definidas a nivel de un espacio de nombres solo pueden ser declaradas como public o internal, y si no llevan un modificador de accesibilidad, por defecto sern internal, es decir sern visibles en todo el proyecto actual. Por otro lado, las interfaces y enumeraciones por defecto sern pblicas. Cuando la clase, estructura, interfaz o enumeracin est definida dentro de otro tipo, la accesibilidad predeterminada ser private, pero admitirn cualquiera de los modificadores, salvo las interfaces y enumeraciones que no pueden ser protected. Por otro lado, los miembros de esos tipos tambin permiten diferentes niveles de accesibilidad, en el caso de las interfaces y enumeraciones, siempre sern pblicos, aunque no se permite el uso de esa instruccin. Los miembros de as clases y estructuras sern privados de forma predeterminada, en el caso de las clases, en esos miembros podemos indicar cualquiera de los cinco niveles de accesibilidad, mientras que en las estructuras no podremos declarar ningn miembro como protected o protected internal, ya que una estructura no puede usarse como base de otro tipo de datos.

Anidacin de tipos
Tal como hemos comentado en la seccin, podemos declarar tipos dentro de otros tipos, por tanto el mbito y accesibilidad de esos tipos dependen del mbito y accesibilidad del tipo que los contiene. Por ejemplo, si declaramos una clase con acceso internal, cualquier tipo que esta clase contenga siempre estar supeditado al mbito de esa clase, por tanto si declaramos otro tipo interno, aunque lo declaremos como public, nunca estar ms accesible que la clase contenedora, aunque en estos casos no habr ningn tipo de confusin, ya que para acceder a los tipos declarados dentro de otros tipos siempre tendremos que indicar la clase que los contiene. En el siguiente cdigo podemos ver cmo declarar dos clases "anidadas". Tal como podemos comprobar, para acceder a la clase Salario debemos indicar la clase Cliente, ya que la nica forma de acceder a una clase anidada es mediante la clase contenedora.
internal class Cliente { public string Nombre;

public class Salario { public decimal Importe; } }

// Para usar la clase Salario debemos declararla de esta forma: Cliente.Salario s = new Cliente.Salario(); s.Importe = 2200;

Los tipos anidables


Las clases y estructuras pueden contener otros tipos, mientras que las interfaces y enumeraciones no pueden contener otros tipos anidados.

Los espacios de nombres pueden anidarse dentro de otros espacios de nombres y estos pueden contener definiciones de cualquiera de los tipos que C# nos permite crear.

El nombre completo de un tipo


Tal como hemos visto, al poder declarar tipos dentro de otros tipos y estos a su vez pueden estar definidos en espacios de nombres, podemos decir que el nombre "completo" de un tipo cualquiera estar formado por el/los espacios de nombres y el/los tipos que los contiene, por ejemplo si la clase Cliente definida anteriormente est a su vez dentro del espacio de nombres Ambitos, el nombre completo ser: Ambitos.Cliente y el nombre completo de la clase Salario ser: Ambitos.Cliente.Salario. Aunque para acceder a la clase Cliente no es necesario indicar el espacio de nombres, al menos si la queremos usar desde cualquier otro tipo declarado dentro de ese espacio de nombres, pero si nuestra intencin es usarla desde otro espacio de nombre externo a Ambitos, en ese caso si que tendremos que usar el nombre completo. Por ejemplo, en el siguiente cdigo tenemos dos espacios de nombres que no estn anidados, cada uno de ellos declara una clase y desde una de ellas queremos acceder a la otra clase, para poder hacerlo debemos indicar el nombre completo, ya que en caso contrario, el compilador de Visual C# 2005 sera incapaz de saber a que clase queremos acceder.
namespace Uno { public class Clase1 { public string Nombre; } }

namespace Dos { public class Clase2 { public string Nombre; public void Prueba() {

Uno.Clase1 c1 = new Uno.Clase1(); c1.Nombre = "Pepe"; } } }

Esto mismo lo podemos aplicar en el caso de que tengamos dos clases con el mismo nombre en espacios de nombres distintos.

Nota: En el mismo proyecto podemos tener ms de una declaracin de un espacio de nombres con el mismo nombre, en estos casos el compilador lo tomar como si todas las clases definidas estuvieran dentro del mismo espacio de nombres, aunque estos estn definidos en ficheros diferentes.

Importacin de espacios de nombres


Tal como hemos comentado, los espacios de nombres pueden contener otros espacios de nombres y estos a su vez tambin pueden contener otros espacios de nombres o clases, y como hemos visto, para poder acceder a una clase que no est dentro del mismo espacio de nombres debemos indicar el "nombre completo". Para evitar estar escribiendo todos los espacios de nombres en los que est la clase que nos interesa declarar, podemos usar una especie de acceso directo o para que lo entendamos mejor, podemos crear una especie de "Path", de forma que al declarar una variable, si esta no est definida en el espacio de nombres actual, el compilador busque en todos los espacios de nombres incluidos en esas rutas (paths). Esto lo conseguimos usando la instruccin using seguida del espacio de nombres que queremos importar o incluir en el path de los espacios de nombres. Podemos usar tantas importaciones de espacios de nombres como necesitemos y estas siempre deben aparecer al principio del fichero. Por ejemplo, si tenemos el cdigo anterior y hacemos la importacin del espacio de nombres en el que est definida la clase Clase1:
using Uno;

podremos acceder a esa clase de cualquiera de estas dos formas:


Uno.Clase1 c1 = new Uno.Clase1();

Clase1 c1 = new Clase1();

Alias de espacios de nombres


Si hacemos demasiadas importaciones de nombres, el problema con el que nos podemos encontrar es que el IntelliSense de Visual C# 2005 no sea de gran ayuda, ya que mostrar una gran cantidad de clases, y seguramente nos resultar ms difcil encontrar la clase a la que queremos acceder, o tambin podemos encontrarnos en ocasiones en las que nos interese usar un nombre corto para acceder a las clases contenidas en un espacio de nombres, por ejemplo, si queremos indicar de forma explcita las clases de un espacio de nombres como el de System.IO, podemos hacerlo de esta forma:
using io = System.IO;

De esta forma podemos usar el "alias" io para acceder a las clases y dems tipos definidos en ese espacio de nombres. En la figura 2.7 podemos ver que al escribir esa palabra, el IntelliSense nos muestra un mensaje de que realmente esa palabra es el espacio de nombres System.IO. En la figura 2.8 al escribir el punto, podemos ver los miembros del espacio de nombres al que hace referencia el alias io.

Figura 2.7. IntelliSense y los alias a los espacios de nombres

También podría gustarte