Paquetes y espacios de nombres

Los conceptos de paquete y espacio de nombres están relacionados. Los paquetes permiten agrupar definiciones de clase de una manera que permite compartir código fácilmente y minimiza los conflictos de nomenclatura. Los espacios de nombres permiten controlar la visibilidad de los identificadores, como los nombres de propiedades y métodos, y pueden aplicarse a código tanto dentro como fuera de un paquete. Los paquetes permiten organizar los archivos de clase y los espacios de nombres permiten administrar la visibilidad de propiedades y métodos individuales.

Paquetes

En ActionScript 3.0, los paquetes se implementan con espacios de nombres, pero son un concepto distinto. Al declarar un paquete, se crea implícitamente un tipo especial de espacio de nombres que se conoce en tiempo de compilación. Si los espacios de nombres se crean explícitamente, no se conocerán necesariamente en tiempo de compilación.

En el ejemplo siguiente se utiliza la directiva package para crear un paquete sencillo que contiene una clase:

package samples 
{ 
    public class SampleCode 
    { 
        public var sampleGreeting:String; 
        public function sampleFunction() 
        { 
            trace(sampleGreeting + " from sampleFunction()"); 
        } 
    } 
}

El nombre de la clase de este ejemplo es SampleCode. Debido a que la clase se encuentra en el interior del paquete samples, el compilador califica el nombre de clase automáticamente en tiempo de compilación como su nombre completo: samples.SampleCode. El compilador también califica los nombres de propiedades y métodos, de forma que sampleGreeting y sampleFunction() se convierten en samples.SampleCode.sampleGreeting y samples.SampleCode.sampleFunction(), respectivamente.

Muchos desarrolladores, especialmente los que tienen experiencia en programación con Java, pueden elegir colocar únicamente clases en el nivel superior de un paquete. Sin embargo, ActionScript 3.0 no sólo admite clases en el nivel superior de un paquete, sino también variables, funciones e incluso sentencias. Un uso avanzado de esta característica consiste en definir un espacio de nombres en el nivel superior de un paquete de forma que esté disponible para todas las clases del paquete. Sin embargo, hay que tener en cuenta que sólo se admiten dos especificadores de acceso en el nivel superior de un paquete: public e internal. A diferencia de Java, que permite declarar clases anidadas como privadas, ActionScript 3.0 no admite clases anidadas privadas ni anidadas.

Sin embargo, en muchos otros aspectos los paquetes de ActionScript 3.0 son similares a los paquetes del lenguaje de programación Java. Como se puede ver en el ejemplo anterior, las referencias de nombre completo a paquetes se expresan con el operador punto (.), igual que en Java. Se pueden utilizar paquetes para organizar el código en una estructura jerárquica intuitiva que puedan usar otros programadores. Esto permite compartir código fácilmente, ya que ofrece una manera de crear un paquete para compartirlo con otros y de utilizar en el código paquetes creados por otros.

El uso de paquetes también ayuda a garantizar que los nombres de los identificadores utilizados son únicos y no entran en conflicto con otros nombres de identificador. De hecho, se podría decir que ésta es la ventaja principal de los paquetes. Por ejemplo, dos programadores que desean compartir código pueden haber creado una clase denominada SampleCode. Sin los paquetes, esto crearía un conflicto de nombres y la única resolución sería cambiar el nombre de una de las clases. Sin embargo, con los paquetes el conflicto de nombres se evita fácilmente colocando una de las clases (o las dos, preferiblemente) en paquetes con nombres únicos.

También se pueden incluir puntos incorporados en el nombre de paquete para crear paquetes anidados. Esto permite crear una organización jerárquica de paquetes. Un buen ejemplo de ello es el paquete flash.display que proporciona ActionScript 3.0. Este paquete se anida dentro del paquete flash.

La mayor parte de ActionScript 3.0 se organiza en el paquete flash. Por ejemplo, el paquete flash.display contiene la API de la lista de visualización y el paquete flash.events contiene el nuevo modelo de eventos.

Creación de paquetes

ActionScript 3.0 proporciona una gran flexibilidad para organizar los paquetes, las clases y los archivos de código fuente. Las versiones anteriores de ActionScript sólo permitían una clase por archivo de código fuente y requerían que el nombre del archivo coincidiera con el nombre de la clase. ActionScript 3.0 permite incluir varias clases en un archivo de código fuente, pero sólo puede estar disponible una clase de cada archivo para el código externo a ese archivo. Es decir, sólo se puede declarar una clase de cada archivo en una declaración de paquete. Hay que declarar las clases adicionales fuera de la definición de paquete, lo que hace que estas clases sean invisibles para el código externo a ese archivo de código fuente. El nombre de clase declarado en la definición de paquete debe coincidir con el nombre del archivo de código fuente.

ActionScript 3.0 también proporciona más flexibilidad para la declaración de paquetes. En versiones anteriores de ActionScript, los paquetes sólo representaban directorios en los que se colocaban archivos de código fuente y no se declaraban con la sentencia package, sino que se incluía el nombre de paquete como parte del nombre completo de clase en la declaración de clase. Aunque los paquetes siguen representando directorios en ActionScript 3.0, pueden contener algo más que clases. En ActionScript 3.0 se utiliza la sentencia package para declarar un paquete, lo que significa que también se pueden declarar variables, funciones y espacios de nombres en el nivel superior de un paquete. Incluso se pueden incluir sentencias ejecutables en el nivel superior de un paquete. Si se declaran variables, funciones o espacios de nombres en el nivel superior de un paquete, los únicos atributos disponibles en ese nivel son public e internal, y sólo una declaración de nivel de paquete por archivo puede utilizar el atributo public, independientemente de que la declaración sea una clase, una variable, una función o un espacio de nombres.

Los paquetes son útiles para organizar el código y para evitar conflictos de nombres. No se debe confundir el concepto de paquete con el concepto de herencia de clases, que no está relacionado con el anterior. Dos clases que residen en el mismo paquete tendrán un espacio de nombres común, pero no estarán necesariamente relacionadas entre sí de ninguna otra manera. Asimismo, un paquete anidado puede no tener ninguna relación semántica con su paquete principal.

Importación de paquetes

Si se desea utilizar una clase que está dentro un paquete, se debe importar el paquete o la clase específica. Esto varía con respecto a ActionScript 2.0, donde la importación de clases era opcional.

Por ejemplo, tenga en cuenta el ejemplo de la clase SampleCode presentada anteriormente. Si la clase reside en un paquete denominado samples, hay que utilizar una de las siguientes sentencias de importación antes de utilizar la clase SampleCode:

import samples.*;

o

import samples.SampleCode;

En general, la sentencias import deben ser lo más específicas posible. Si se pretende utilizar la clase SampleCode desde el paquete samples, hay que importar únicamente la clase SampleCode, no todo el paquete al que pertenece. La importación de paquetes completos puede producir conflictos de nombres inesperados.

También se debe colocar el código fuente que define el paquete o la clase en la ruta de clases. La ruta de clases es una lista de rutas de directorio locales definida por el usuario que determina dónde buscará el compilador los paquetes y las clases importados. La ruta de clases se denomina a veces ruta de compilación o ruta de código fuente.

Tras importar correctamente la clase o el paquete, se puede utilizar el nombre completo de la clase (samples.SampleCode) o simplemente el nombre de clase (SampleCode).

Los nombres completos son útiles cuando hay ambigüedad en el código a causa de clases, métodos o propiedades con nombre idénticos, pero pueden ser difíciles de administrar si se usan para todos los identificadores. Por ejemplo, la utilización del nombre completo produce código demasiado extenso al crear una instancia de la clase SampleCode:

var mySample:samples.SampleCode = new samples.SampleCode();

A medida que aumentan los niveles de paquetes anidados, la legibilidad del código disminuye. En las situaciones en las que se esté seguro de que los identificadores ambiguos no constituirán un problema, se puede hacer el código más legible utilizando identificadores sencillos. Por ejemplo, al crear una nueva instancia de la clase SampleCode, el resultado será mucho menos extenso si se utiliza sólo el identificador de clase:

var mySample:SampleCode = new SampleCode();

Si se intenta utilizar nombres de identificador sin importar primero el paquete o la clase apropiados, el compilador no podrá encontrar las definiciones de clase. Por otra parte, si se importa un paquete o una clase, cualquier intento de definir un nombre que entre en conflicto con un nombre importado generará un error.

Cuando se crea un paquete, el especificador de acceso predeterminado para todos los miembros del paquete es internal, lo que significa que, de manera predeterminada, los miembros del paquete sólo estarán visibles para los otros miembros del paquete. Si se desea que una clase esté disponible para código externo al paquete, se debe declarar la clase como public. Por ejemplo, el siguiente paquete contiene dos clases, SampleCode y CodeFormatter:

// SampleCode.as file 
package samples 
{ 
    public class SampleCode {} 
} 
 
// CodeFormatter.as file 
package samples 
{ 
    class CodeFormatter {} 
}

La clase SampleCode está visible fuera del paquete porque se ha declarado como una clase public. Sin embargo, la clase CodeFormatter sólo está visible dentro del mismo paquete samples. Si se intenta acceder la clase CodeFormatter fuera del paquete samples, se generará un error, como se indica en el siguiente ejemplo:

import samples.SampleCode; 
import samples.CodeFormatter; 
var mySample:SampleCode = new SampleCode(); // okay, public class 
var myFormatter:CodeFormatter = new CodeFormatter(); // error

Si se desea que ambas clases estén disponibles para código externo al paquete, se deben declarar las dos como public. No se puede aplicar el atributo public a la declaración del paquete.

Los nombres completos son útiles para resolver conflictos de nombres que pueden producirse al utilizar paquetes. Este escenario puede surgir si se importan dos paquetes que definen clases con el mismo identificador. Por ejemplo, considérese el siguiente paquete, que también tiene una clase denominada SampleCode:

package langref.samples 
{ 
    public class SampleCode {} 
}

Si se importan ambas clases de la manera siguiente, se producirá un conflicto de nombres al utilizar la clase SampleCode:

import samples.SampleCode; 
import langref.samples.SampleCode; 
var mySample:SampleCode = new SampleCode(); // name conflict

El compilador no sabe qué clase SampleCode debe utilizar. Para resolver este conflicto, hay que utilizar el nombre completo de cada clase, de la manera siguiente:

var sample1:samples.SampleCode = new samples.SampleCode(); 
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
Nota: los programadores con experiencia en C++ suelen confundir la sentencia import con #include. La directiva #include es necesaria en C++ porque los compiladores de C++ procesan un archivo cada vez y no buscan definiciones de clases en otros archivos, a menos que se incluya explícitamente un archivo de encabezado. ActionScript 3.0 tiene una directiva include, pero no está diseñada para importar clases y paquetes. Para importar clases o paquetes en ActionScript 3.0, hay que usar la sentencia import y colocar el archivo de código fuente que contiene el paquete en la ruta de clases.

Espacios de nombres

Los espacios de nombres ofrecen control sobre la visibilidad de las propiedades y los métodos que se creen. Los especificadores de control de acceso public, private, protected e internal son espacios de nombres incorporados. Si estos especificadores de control de acceso predefinidos no se adaptan a las necesidades del programador, es posible crear espacios de nombres personalizados.

Para los programadores que estén familiarizados con los espacios de nombres XML, gran parte de lo que se va a explicar no resultará nuevo, aunque la sintaxis y los detalles de la implementación de ActionScript son ligeramente distintos de los de XML. Si nunca se ha trabajado con espacios de nombres, el concepto en sí es sencillo, pero hay que aprender la terminología específica de la implementación.

Para comprender mejor cómo funcionan los espacios de nombres, es necesario saber que el nombre de una propiedad o un método siempre contiene dos partes: un identificador y un espacio de nombres. El identificador es lo que generalmente se considera un nombre. Por ejemplo, los identificadores de la siguiente definición de clase son sampleGreeting y sampleFunction():

class SampleCode 
{ 
    var sampleGreeting:String; 
    function sampleFunction () { 
        trace(sampleGreeting + " from sampleFunction()"); 
    } 
}

Siempre que las definiciones no estén precedidas por un atributo de espacio de nombres, sus nombres se califican mediante el espacio de nombres internal predeterminado, lo que significa que sólo estarán visibles para los orígenes de llamada del mismo paquete. Si el compilador está configurado en modo estricto, emite una advertencia para indicar que el espacio de nombres internal se aplica a cualquier identificador que no tenga un atributo de espacio de nombres. Para asegurarse de que un identificador esté disponible en todas partes, hay que usar específicamente el atributo public como prefijo del nombre de identificador. En el ejemplo de código anterior, sampleGreeting y sampleFunction() tienen internal como valor de espacio de nombres.

Se deben seguir tres pasos básicos al utilizar espacios de nombres. En primer lugar, hay que definir el espacio de nombres con la palabra clave namespace. Por ejemplo, el código siguiente define el espacio de nombres version1:

namespace version1;

En segundo lugar, se aplica el espacio de nombres utilizándolo en lugar de utilizar un especificador de control de acceso en una declaración de propiedad o método. El ejemplo siguiente coloca una función denominada myFunction() en el espacio de nombres version1:

version1 function myFunction() {}

En tercer lugar, tras aplicar el espacio de nombres, se puede hacer referencia al mismo con la directiva use o calificando el nombre de un identificador con un espacio de nombres. En el ejemplo siguiente se hace referencia a la función myFunction() mediante la directiva use:

use namespace version1; 
myFunction();

También se puede utilizar un nombre completo para hacer referencia a la función myFunction(), como se indica en el siguiente ejemplo:

version1::myFunction();

Definición de espacios de nombres

Los espacios de nombres contienen un valor, el Identificador uniforme de recurso (URI), que a veces se denomina nombre del espacio de nombres. El URI permite asegurarse de que la definición del espacio de nombres es única.

Para crear un espacio de nombres se declara una definición de espacio de nombres de una de las dos maneras siguientes. Se puede definir un espacio de nombres con un URI explícito, de la misma manera que se define un espacio de nombres XML, o se puede omitir el URI. En el siguiente ejemplo se muestra la manera de definir un espacio de nombres mediante un URI:

namespace flash_proxy = "http://www.adobe.com/flash/proxy";

El URI constituye una cadena de identificación única para ese espacio de nombres. Si se omite el URI, como en el siguiente ejemplo, el compilador creará una cadena de identificación interna única en lugar del URI. El usuario no tiene acceso a esta cadena de identificación interna.

namespace flash_proxy;

Una vez definido un espacio de nombres, con o sin URI, ese espacio de nombres no podrá definirse de nuevo en el mismo ámbito. Si se intenta definir un espacio de nombres definido previamente en el mismo ámbito, se producirá un error del compilador.

Si se define un espacio de nombres dentro de un paquete o una clase, el espacio de nombres puede no estar visible para código externo al paquete o la clase, a menos que se use el especificador de control de acceso apropiado. Por ejemplo, el código siguiente muestra el espacio de nombres flash_proxy definido en el paquete flash.utils. En el siguiente ejemplo, la falta de un especificador de control de acceso significa que el espacio de nombres flash_proxy sólo estará visible para el código del paquete flash.utils y no estará visible para el código externo al paquete:

package flash.utils 
{ 
    namespace flash_proxy; 
}

El código siguiente utiliza el atributo public para hacer que el espacio de nombres flash_proxy esté visible para el código externo al paquete:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

Aplicación de espacios de nombres

Aplicar un espacio de nombres significa colocar una definición en un espacio de nombres. Entre las definiciones que se puede colocar en espacios de nombres se incluyen funciones, variables y constantes (no se puede colocar una clase en un espacio de nombres personalizado).

Considérese, por ejemplo, una función declarada con el espacio de nombres de control de acceso public. Al utilizar el atributo public en una definición de función se coloca la función en el espacio de nombres public, lo que hace que esté disponible para todo el código. Una vez definido un espacio de nombres, se puede utilizar el espacio de nombres definido de la misma manera que se utilizaría el atributo public y la definición estará disponible para el código que puede hacer referencia al espacio de nombres personalizado. Por ejemplo, si se define un espacio de nombres example1, se puede añadir un método denominado myFunction() utilizando example1 como un atributo, como se indica en el siguiente ejemplo:

namespace example1; 
class someClass 
{ 
    example1 myFunction() {} 
}

Si se declara el método myFunction() con el espacio de nombres example1 como un atributo, significa que el método pertenece al espacio de nombres example1.

Se debe tener en cuenta lo siguiente al aplicar espacios de nombres:

  • Sólo se puede aplicar un espacio de nombres a cada declaración.

  • No hay manera de aplicar un atributo de espacio de nombres a más de una definición simultáneamente. Es decir, si se desea aplicar el espacio de nombres a diez funciones distintas, se debe añadir el espacio de nombres como un atributo a cada una de las diez definiciones de función.

  • Si se aplica un espacio de nombres, no se puede especificar también un especificador de control de acceso, ya que los espacios de nombres y los especificadores de control de acceso son mutuamente excluyentes. Es decir, no se puede declarar una función o propiedad como public, private, protected o internal y aplicar también el espacio de nombres.

Referencia a un espacio de nombres

No es necesario hacer referencia explícita a un espacio de nombres al usar un método o una propiedad declarados con alguno de los espacios de nombres de control de acceso, como public, private, protected e internal. Esto se debe a que el acceso a estos espacios de nombres especiales se controla por el contexto. Por ejemplo, las definiciones colocadas en el espacio de nombres private estarán disponibles automáticamente para el código de la misma clase. Sin embargo, para los espacios de nombres personalizados que se definan no existirá este control mediante el contexto. Para poder utilizar un método o una propiedad que se ha colocado en un espacio de nombres personalizado, se debe hacer referencia al espacio de nombres.

Se puede hacer referencia a espacios de nombres con la directiva use namespace o se puede calificar el nombre con el espacio de nombres mediante el signo calificador de nombre (::). Al hacer referencia a un espacio de nombres con la directiva use namespace “se abre” el espacio de nombres, de forma que se puede aplicar a cualquier identificador que no esté calificado. Por ejemplo, si se define el espacio de nombres example1, se puede acceder a nombres de ese espacio de nombres mediante use namespace example1:

use namespace example1; 
myFunction();

Es posible abrir más de un espacio de nombres simultáneamente. Cuando se abre un espacio de nombres con use namespace, permanece abierto para todo el bloque de código en el que se abrió. No hay forma de cerrar un espacio de nombres explícitamente.

Sin embargo, si hay más de un espacio de nombres abierto, aumenta la probabilidad de que se produzcan conflictos de nombres. Si se prefiere no abrir un espacio de nombres, se puede evitar la directiva use namespace calificando el nombre del método o la propiedad con el espacio de nombres y el signo calificador de nombre. Por ejemplo, el código siguiente muestra la manera de calificar el nombre myFunction() con el espacio de nombres example1:

example1::myFunction();

Uso de espacios de nombres

Puede encontrar un ejemplo real de un espacio de nombres que se utiliza para evitar conflictos de nombre en la clase flash.utils.Proxy que forma parte de ActionScript 3.0. La clase Proxy, que es la sustitución de la propiedad Object.__resolve de ActionScript 2.0, permite interceptar referencias a propiedades o métodos no definidos antes de que se produzca un error. Todos los métodos de la clase Proxy residen en el espacio de nombres flash_proxy para evitar conflictos de nombres.

Para entender mejor cómo se utiliza el espacio de nombres flash_proxy, hay que entender cómo se utiliza la clase Proxy. La funcionalidad de la clase Proxy sólo está disponible para las clases que heredan de ella. Es decir, si se desea utilizar los métodos de la clase Proxy en un objeto, la definición de clase del objeto debe ampliar la clase Proxy. Por ejemplo, si desea se interceptar intentos de llamar a un método no definido, se debe ampliar la clase Proxy y después reemplazar el método callProperty() de la clase Proxy.

La implementación de espacios de nombres es generalmente un proceso en tres pasos consistente en definir y aplicar un espacio de nombres, y después hacer referencia al mismo. Sin embargo, como nunca se llama explícitamente a ninguno de los métodos de la clase Proxy, sólo se define y aplica el espacio de nombres flash_proxy, pero nunca se hace referencia al mismo. ActionScript 3.0 define el espacio de nombres flash_proxy y lo aplica en la clase Proxy. El código sólo tiene que aplicar el espacio de nombres flash_proxy a las clases que amplían la clase Proxy.

El espacio de nombres flash_proxy se define en el paquete flash.utils de una manera similar a la siguiente:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

El espacio de nombres se aplica a los métodos de la clase Proxy, como se indica en el siguiente fragmento de dicha clase:

public class Proxy 
{ 
    flash_proxy function callProperty(name:*, ... rest):* 
    flash_proxy function deleteProperty(name:*):Boolean 
    ... 
}

Como se indica en el código siguiente, se debe importar primero la clase Proxy y el espacio de nombres flash_proxy. A continuación se debe declarar la clase de forma que amplíe la clase Proxy (también se debe añadir el atributo dynamic si se compila en modo estricto). Al sustituir el método callProperty(), se debe utilizar el espacio de nombres flash_proxy.

package 
{ 
    import flash.utils.Proxy; 
    import flash.utils.flash_proxy; 
 
    dynamic class MyProxy extends Proxy 
    { 
        flash_proxy override function callProperty(name:*, ...rest):* 
        { 
            trace("method call intercepted: " + name); 
        } 
    } 
}

Si se crea una instancia de la clase MyProxy y se llama a un método no definido, como el método testing() llamado en el ejemplo siguiente, el objeto Proxy intercepta la llamada al método y ejecuta las sentencias del método callProperty() sustituido (en este caso, una simple sentencia trace()).

var mySample:MyProxy = new MyProxy(); 
mySample.testing(); // method call intercepted: testing

Tener los métodos de la clase Proxy dentro del espacio de nombres flash_proxy ofrece dos ventajas. En primer lugar, tener un espacio de nombres independiente reduce el desorden en la interfaz pública de cualquier clase que amplíe la clase Proxy. (Hay aproximadamente una docena de métodos en la clase Proxy que se pueden sustituir; todos ellos han sido diseñados para no ser llamados directamente. Colocarlos todos en el espacio de nombres public podría provocar confusiones.) En segundo lugar, el uso del espacio de nombres flash_proxy evita los conflictos de nombres en caso de que la subclase de Proxy contenga métodos de instancia con nombres que coincidan con los de los métodos de la clase Proxy. Por ejemplo, supongamos que un programador desea asignar a uno de sus métodos el nombre callProperty(). El código siguiente es aceptable porque su versión del método callProperty() está en un espacio de nombres distinto:

dynamic class MyProxy extends Proxy 
{ 
    public function callProperty() {} 
    flash_proxy override function callProperty(name:*, ...rest):* 
    { 
        trace("method call intercepted: " + name); 
    } 
}

Los espacios de nombres también pueden ser útiles cuando se desea proporcionar acceso a métodos o propiedades de una manera que se no puede realizar con los cuatro especificadores de control de acceso (public, private, internal y protected). Por ejemplo, un programador puede tener algunos métodos de utilidad repartidos por varios paquetes. Desea que estos métodos estén disponibles para todos los paquetes, pero no quiere que sean públicos. Para ello, se puede crear un espacio de nombres y utilizarlo como un especificador de control de acceso especial.

En el ejemplo siguiente se utiliza un espacio de nombres definido por el usuario para agrupar dos funciones que residen en paquetes distintos. Al agruparlos en el mismo espacio de nombres, se puede hacer que ambas funciones estén visibles para una clase o un paquete mediante una única sentencia use namespace.

En este ejemplo se utilizan cuatro archivos para ilustrar la técnica. Todos los archivos deben estar en la ruta de clases. El primer archivo, myInternal.as, se utiliza para definir el espacio de nombres myInternal. Como el archivo está en un paquete denominado example, se debe colocar en una carpeta denominada example. El espacio de nombres se marca como public de forma que se pueda importar en otros paquetes.

// myInternal.as in folder example 
package example 
{ 
    public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples"; 
}

Los archivos Utility.as y Helper.as definen las clases que contienen los métodos que deben estar disponibles para otros paquetes. La clase Utility está en el paquete example.alpha, lo que significa que se debe colocar el archivo dentro de una subcarpeta de la carpeta example denominada alpha. La clase Helper está en el paquete example.beta, por lo que se debe colocar el archivo dentro de otra subcarpeta de la carpeta example denominada beta. Ambos paquetes, example.alpha y example.beta, deben importar el espacio de nombres antes de utilizarlo.

// Utility.as in the example/alpha folder 
package example.alpha 
{ 
    import example.myInternal; 
     
    public class Utility 
    { 
        private static var _taskCounter:int = 0; 
     
        public static function someTask() 
        { 
            _taskCounter++; 
        } 
         
        myInternal static function get taskCounter():int 
        { 
            return _taskCounter; 
        } 
    } 
} 
 
// Helper.as in the example/beta folder 
package example.beta 
{ 
    import example.myInternal; 
     
    public class Helper 
    { 
        private static var _timeStamp:Date; 
         
        public static function someTask() 
        { 
            _timeStamp = new Date(); 
        } 
         
        myInternal static function get lastCalled():Date 
        { 
            return _timeStamp; 
        } 
    } 
}

El cuarto archivo, NamespaceUseCase.as, es la clase principal de la aplicación, y debe estar en el mismo nivel que la carpeta example. En Flash Professional, esta clase se utilizaría como la clase de documento para el archivo FLA. La clase NamespaceUseCase también importa el espacio de nombres myInternal y lo utiliza para llamar a los dos métodos estáticos que residen en los otros paquetes. El ejemplo utiliza métodos estáticos sólo para simplificar el código. Se pueden colocar tanto métodos estáticos como métodos de instancia en el espacio de nombres myInternal.

// NamespaceUseCase.as 
package 
{ 
    import flash.display.MovieClip; 
    import example.myInternal; // import namespace 
    import example.alpha.Utility;// import Utility class 
    import example.beta.Helper;// import Helper class 
     
    public class NamespaceUseCase extends MovieClip 
    { 
        public function NamespaceUseCase() 
        { 
            use namespace myInternal; 
             
            Utility.someTask(); 
            Utility.someTask(); 
            trace(Utility.taskCounter); // 2 
             
            Helper.someTask(); 
            trace(Helper.lastCalled); // [time someTask() was last called] 
        } 
    } 
}