패키지 및 네임스페이스

패키지와 네임스페이스는 서로 관련된 개념입니다. 패키지를 사용하면 클래스 정의를 묶음 처리하여 쉽게 코드를 공유하고 이름이 충돌하는 것을 최소화할 수 있습니다. 네임스페이스를 사용하면 속성 및 메서드 이름과 같은 식별자의 가시성을 제어할 수 있습니다. 네임스페이스는 패키지 내부 또는 외부에 있는 코드에 적용할 수 있습니다. 패키지를 사용하여 클래스 파일을 구성할 수 있으며, 네임스페이스를 사용하여 개별 속성 및 메서드의 가시성을 관리할 수 있습니다.

패키지

ActionScript 3.0의 패키지는 네임스페이스로 구현되지만 네임스페이스와 동일한 의미로 사용되지는 않습니다. 패키지를 선언하면 특수한 유형의 네임스페이스가 자동으로 만들어지며 이 네임스페이스는 컴파일 타임에 확인할 수 있습니다. 명시적으로 만든 네임스페이스는 컴파일 타임에 확인되지 않을 수도 있습니다.

다음 예제에서는 package 지시문을 사용하여 하나의 클래스가 포함된 단순한 패키지를 만듭니다.

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

이 예제에서 클래스 이름은 SampleCode입니다. 이 클래스는 samples 패키지 내에 있으므로 클래스 이름이 컴파일 타임에 컴파일러에 의해 samples.SampleCode로 자동으로 정규화됩니다. 또한 컴파일러에서 모든 속성 또는 메서드의 이름도 정규화하므로 sampleGreetingsampleFunction()은 각각 samples.SampleCode.sampleGreetingsamples.SampleCode.sampleFunction()이 됩니다.

대부분의 개발자 특히, Java 프로그래밍 경력이 있는 개발자는 패키지의 최상위에 클래스만 배치하려고 할 수 있습니다. 그러나 ActionScript 3.0에서는 패키지의 최상위에 클래스뿐만 아니라 변수, 함수 및 명령문도 배치할 수 있습니다. 이 기능의 고급 용도 중 하나는 패키지의 최상위에 네임스페이스를 정의하여 해당 패키지의 모든 클래스에서 사용할 수 있다는 것입니다. 그러나 패키지의 최상위에서는 두 개의 액세스 지정자, 즉 publicinternal만 사용할 수 있습니다. 중첩된 클래스를 전용(private)으로 선언할 수 있는 Java와 달리 ActionScript 3.0에서는 중첩된 클래스 또는 전용 클래스를 지원하지 않습니다.

ActionScript 3.0 패키지는 여러 면에서 Java 프로그래밍 언어로 구현된 패키지와 유사합니다. 이전 예제에서 확인할 수 있듯이 Java의 경우와 마찬가지로 도트 연산자(.)를 사용하여 정규화된 패키지 참조를 표시합니다. 패키지를 사용하면 코드를 직관적인 계층 구조로 구성하여 다른 프로그래머에게 제공할 수 있습니다. 이와 같이 다른 사람과 공유할 패키지를 만들고 다른 사람이 만든 패키지를 코드에 사용할 수 있으므로 코드 공유가 촉진됩니다.

패키지를 사용하면 사용할 식별자 이름을 고유하게 만들어 다른 식별자 이름과 충돌하지 않도록 할 수도 있습니다. 실제로 일부 사용자는 이 기능이 패키지의 주요 장점이라고 말합니다. 예를 들어 서로의 코드를 공유하려는 두 명의 프로그래머가 SampleCode라는 클래스를 각각 만들 수 있습니다. 패키지를 사용하지 않으면 이름이 충돌하며 이 문제는 하나의 클래스 이름을 변경해야 해결할 수 있습니다. 그러나 패키지를 사용하면 두 클래스 중 하나를 패키지에 배치하거나 둘 모두를 이름이 다른 두 개의 패키지에 각각 배치하여 이름 충돌을 피할 수 있습니다.

패키지 이름에 도트를 사용하여 중첩된 패키지를 만들 수도 있습니다. 이렇게 하면 패키지의 계층적 구조를 만들 수 있습니다. ActionScript 3.0에서 제공하는 flash.display 패키지는 이에 대한 좋은 예입니다. flash.display 패키지는 flash 패키지 내에 중첩됩니다.

ActionScript 3.0은 대부분 flash 패키지 아래에 구성됩니다. 예를 들어 flash.display 패키지에 표시 목록 API가 포함되어 있으며, flash.events 패키지에는 새 이벤트 모델이 포함되어 있습니다.

패키지 만들기

ActionScript 3.0에서는 패키지, 클래스 및 소스 파일을 매우 유연하게 구성할 수 있습니다. 이전 버전의 ActionScript에서는 소스 파일당 하나의 클래스만 허용되었으며 소스 파일 이름이 클래스 이름과 일치해야 했습니다. ActionScript 3.0에서는 하나의 소스 파일에 여러 클래스를 포함할 수 있지만 해당 파일의 외부에 있는 코드에는 각 파일의 클래스를 하나만 사용할 수 있습니다. 즉, 패키지 선언 내에는 각 파일의 클래스를 하나만 선언할 수 있습니다. 추가적인 클래스는 패키지 정의 외부에 선언하여 소스 파일 외부에 있는 코드에서 추가적인 클래스를 참조할 수 없도록 합니다. 패키지 정의 내에 선언된 클래스 이름은 소스 파일 이름과 일치해야 합니다.

ActionScript 3.0에서 패키지를 보다 융통성 있게 선언할 수 있습니다. 이전 버전의 ActionScript에서 패키지는 단순히 소스 파일이 있는 디렉토리를 나타냈으며 사용자는 package 문을 사용하여 패키지를 선언하지 않고 클래스 선언에 정규화된 클래스 이름의 일부로 패키지 이름을 포함했습니다. ActionScript 3.0에서도 패키지는 디렉토리를 나타내지만 패키지에 클래스 이외의 요소를 포함할 수 있습니다. ActionScript 3.0에서는 package 문을 사용하여 패키지를 선언하므로 패키지의 최상위에서 변수, 함수 및 네임스페이스를 선언할 수도 있습니다. 또한 패키지의 최상위에 실행 가능한 명령문을 포함할 수 있습니다. 패키지의 최상위에서 변수, 함수 또는 네임스페이스를 선언하는 경우 해당 수준에서 publicinternal 특성만 사용할 수 있으며 선언 대상이 클래스, 변수, 함수 또는 네임스페이스인지에 관계없이 파일당 하나의 패키지 수준 선언에서만 public 특성을 사용할 수 있습니다.

패키지는 코드를 체계화하고 이름 충돌을 방지하는 데 유용합니다. 패키지 개념은 클래스 상속 개념과 관련이 없으므로 이 둘을 혼동해서는 안됩니다. 동일한 패키지에 있는 두 개의 클래스는 공통된 네임스페이스에 있지만 그 외에 다른 방식으로 상호 관련되어야 하는 것은 아닙니다. 마찬가지로 중첩된 패키지와 상위 패키지 간에 아무런 의미적 관련성이 없을 수 있습니다.

패키지 가져오기

패키지 내의 클래스를 사용하려면 패키지 또는 특정 클래스 중 하나를 가져와야 합니다. 이는 클래스 가져오기를 생략해도 되었던 ActionScript 2.0과 다른 점입니다.

예를 들어 앞에서 제공된 SampleCode 클래스 예제에 대해 살펴 보십시오. samples라는 패키지에 있는 SampleCode 클래스를 사용하려면 다음 import 문 중 하나를 사용해야 합니다.

import samples.*;

또는

import samples.SampleCode;

일반적으로 import 문은 최대한 구체적이어야 합니다. samples 패키지에서 SampleCode 클래스만 사용하려는 경우 SampleCode 클래스가 속해 있는 전체 패키지가 아닌 SampleCode 클래스만 가져와야 합니다. 전체 패키지를 가져오면 예기치 못한 이름 충돌이 발생할 수 있습니다.

패키지 또는 클래스를 정의하는 소스 코드도 클래스 경로 내에 배치해야 합니다. 클래스 경로는 컴파일러가 가져온 패키지 및 클래스를 검색할 위치를 결정하는 로컬 디렉토리 경로의 사용자 정의 목록입니다. 클래스 경로는 빌드 경로 또는 소스 경로라고도 합니다.

클래스 또는 패키지를 올바르게 가져오면 정규화된 클래스 이름(samples.SampleCode) 또는 클래스 자체 이름(SampleCode) 중 하나를 사용할 수 있습니다.

정규화된 이름은 동일하게 이름이 지정된 클래스, 메서드 또는 속성으로 인해 코드가 모호해지는 경우 유용하지만 모든 식별자에 사용하면 관리하기 어려울 수 있습니다. 예를 들어 SampleCode 클래스 인스턴스를 인스턴스화할 때 정규화된 이름을 사용하면 코드가 길어집니다.

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

패키지가 중첩될수록 코드의 가독성은 떨어집니다. 모호한 식별자가 문제가 되지 않는 경우에는 간단한 식별자를 사용하여 더 읽기 쉬운 코드를 만들 수 있습니다. 예를 들어 클래스 식별자만 사용하는 경우 다음과 같이 SampleCode 클래스의 새 인스턴스를 인스턴스화하는 것이 훨씬 간단합니다.

var mySample:SampleCode = new SampleCode();

먼저 적절한 패키지 또는 클래스를 가져오지 않고 식별자 이름을 사용하려고 하면 컴파일러에서 클래스 정의를 찾을 수 없게 됩니다. 반면에 패키지 또는 클래스를 가져온 경우 가져온 이름과 충돌하는 이름을 정의하려고 하면 오류가 발생합니다.

패키지를 만든 경우 해당 패키지의 모든 멤버에 대한 기본 액세스 지정자는 internal입니다. 이는 기본적으로 패키지 멤버를 해당 패키지의 다른 멤버만 참조할 수 있다는 것을 의미합니다. 패키지 외부의 코드에서 클래스를 사용할 수 있도록 하려면 해당 클래스를 public으로 선언해야 합니다. 예를 들어 다음 패키지에 SampleCode 및 CodeFormatter 클래스가 포함되어 있습니다.

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

SampleCode 클래스는 public 클래스로 선언되어 있으므로 패키지 외부에서 참조할 수 있습니다. 그러나 CodeFormatter 클래스는 samples 패키지 내에서만 참조할 수 있습니다. samples 패키지 외부에서 CodeFormatter 클래스에 액세스하려고 하면 다음 예제와 같이 오류가 발생합니다.

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

패키지 외부에서 두 클래스를 모두 사용할 수 있도록 하려면 두 클래스를 모두 public으로 선언해야 합니다. 패키지 선언에는 public 특성을 적용할 수 없습니다.

정규화된 이름은 패키지를 사용할 때 발생할 수 있는 이름 충돌 문제를 해결하는 데 유용합니다. 동일한 식별자를 사용하여 클래스를 정의하는 두 개의 패키지를 가져오는 경우 이름 충돌 문제가 발생할 수 있습니다. 예를 들어 마찬가지로 SampleCode라는 클래스가 포함되어 있는 다음 패키지를 살펴보십시오.

package langref.samples 
{ 
    public class SampleCode {} 
}

두 클래스를 모두 가져오면 SampleCode 클래스를 사용할 때 다음과 같이 이름이 충돌하게 됩니다.

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

컴파일러는 어떤 SampleCode 클래스를 사용해야 하는지 알 수 없습니다. 이 충돌 문제를 해결하려면 다음과 같이 각 클래스의 정규화된 이름을 사용해야 합니다.

var sample1:samples.SampleCode = new samples.SampleCode(); 
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
참고: C++ 사용 경력이 있는 프로그래머가 import 문과 #include를 혼동하는 경우가 많습니다. C++ 컴파일러의 경우 파일을 한 번에 하나씩만 처리하고 헤더 파일이 명시적으로 포함되어 있지 않으면 다른 파일에서 클래스 정의를 찾지 않으므로 C++에서 #include 지시문은 필수적인 요소입니다. ActionScript 3.0에는 include 지시문이 있지만 클래스 및 패키지를 가져오기 위한 것이 아닙니다. ActionScript 3.0에서 클래스 또는 패키지를 가져오려면 import 문을 사용하고 패키지가 포함된 소스 파일을 클래스 경로에 배치해야 합니다.

네임스페이스

네임스페이스를 사용하면 사용자가 만든 속성 및 메서드의 가시성을 제어할 수 있습니다. public, private, protectedinternal 액세스 제어 지정자를 내장 네임스페이스로 간주할 수 있습니다. 이러한 미리 정의된 액세스 제어 지정자가 사용자 요구에 적합하지 않은 경우 직접 네임스페이스를 만들 수 있습니다.

ActionScript 구현의 구문 및 세부 사항이 XML의 구문 및 세부 사항과 약간 다르지만 XML 네임스페이스에 익숙한 사용자에게는 이 설명서의 내용이 낯설게 느껴지지 않을 것입니다. 네임스페이스의 개념은 매우 간단하지만 이전에 네임스페이스를 사용하여 작업한 경험이 없는 경우 이를 구현하려면 특정 용어를 익혀야 합니다.

네임스페이스의 작동을 이해하려면 속성 또는 메서드 이름에 식별자 및 네임스페이스가 항상 포함된다는 점을 이해하는 것이 좋습니다. 식별자는 일반적으로 이름으로 간주되는 것을 말합니다. 예를 들어 다음 클래스 정의에서 식별자는 sampleGreetingsampleFunction()입니다.

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

클래스 등을 정의할 때 네임스페이스 특성을 먼저 지정하지 않으면 해당 정의에 사용된 이름이 기본 internal 네임스페이스로 정규화되므로 동일한 패키지에 있는 호출자만 해당 이름을 참조할 수 있습니다. 컴파일러가 엄격 모드로 설정되어 있는 경우 네임스페이스 특성이 없는 모든 식별자에 internal 네임스페이스가 적용된다는 경고가 표시됩니다. 식별자를 모든 범위에서 사용할 수 있도록 하려면 식별자 이름 앞에 public 특성을 명시해야 합니다. 이전 예제 코드에서 sampleGreetingsampleFunction()에는 모두 internal 네임스페이스 값이 적용됩니다.

네임스페이스를 사용할 때 수행해야 할 세 가지 기본 단계는 다음과 같습니다. 첫 번째, namespace 키워드를 사용하여 네임스페이스를 정의해야 합니다. 예를 들어 다음 코드는 version1 네임스페이스를 정의합니다.

namespace version1;

두 번째, 속성 또는 메서드 선언에서 액세스 제어 지정자 대신 네임스페이스를 사용하여 네임스페이스를 적용합니다. 다음 예제에서는 myFunction() 함수를 version1 네임스페이스에 배치합니다.

version1 function myFunction() {}

세 번째, 네임스페이스가 적용되면 use 지시문을 사용하거나 식별자 이름을 네임스페이스로 정규화하여 참조할 수 있습니다. 다음 예제에서는 use 지시문을 통해 myFunction() 함수를 참조합니다.

use namespace version1; 
myFunction();

다음 예제에서 볼 수 있는 것과 같이 정규화된 이름을 사용하여 myFunction() 함수를 참조할 수도 있습니다.

version1::myFunction();

네임스페이스 정의

네임스페이스에는 URI(Uniform Resource Identifier)라는 하나의 값이 포함되며, 이를 네임스페이스 이름이라고도 합니다. URI를 사용하여 네임스페이스 정의를 고유하게 만들 수 있습니다.

두 가지 방법 중 하나로 네임스페이스 정의를 선언하여 네임스페이스를 만듭니다. XML 네임스페이스를 정의하듯이 명시적 URI가 있는 네임스페이스를 정의할 수 있으나 URI를 생략하는 것도 가능합니다. 다음 예제에서는 URI를 사용하여 네임스페이스를 정의하는 방법을 보여 줍니다.

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

URI는 해당 네임스페이스에 대한 고유한 식별 문자열 역할을 합니다. URI를 생략하면 다음 예제에서와 같이 컴파일러에서 URI 대신 고유한 내부 식별 문자열을 만듭니다. 사용자는 이 내부 식별 문자열에 액세스하지 못합니다.

namespace flash_proxy;

URI 사용 여부와 관계없이 한 번 정의한 네임스페이스는 동일한 범위에서 다시 정의할 수 없습니다. 이전에 정의한 네임스페이스를 동일한 범위에서 정의하려고 하면 컴파일러 오류가 발생합니다.

패키지 또는 클래스 내에 네임스페이스가 정의된 경우 적절한 액세스 제어 지정자를 사용하지 않으면 해당 패키지 또는 클래스 외부의 코드에서 네임스페이스를 참조할 수 없습니다. 예를 들어 다음 코드에서는 flash.utils 패키지 내에 정의된 flash_proxy 네임스페이스를 보여 줍니다. 다음 예제에서는 액세스 제어 지정자가 없으므로 flash.utils 패키지 내의 코드에서만 flash_proxy 네임스페이스를 참조할 수 있고 패키지 외부의 모든 코드에서는 참조할 수 없습니다.

package flash.utils 
{ 
    namespace flash_proxy; 
}

다음 코드에서는 패키지 외부의 코드에서 flash_proxy 네임스페이스를 참조할 수 있도록 public 특성을 사용합니다.

package flash.utils 
{ 
    public namespace flash_proxy; 
}

네임스페이스 적용

네임스페이스를 적용한다는 것은 정의를 네임스페이스에 배치하는 것을 의미합니다. 네임스페이스에 배치할 수 있는 정의에는 함수, 변수 및 상수가 있으며 사용자 정의 네임스페이스에 클래스를 배치할 수는 없습니다.

예를 들어 public 액세스 제어 네임스페이스를 사용하여 선언된 함수를 살펴보십시오. 함수 정의에서 public 특성을 사용하여 함수를 공용 네임스페이스에 배치하면 모든 코드에서 해당 함수를 사용할 수 있습니다. 네임스페이스를 정의하면 public 특성을 사용할 때와 동일한 방법으로 정의된 네임스페이스를 사용할 수 있으며, 사용자 정의 네임스페이스를 참조할 수 있는 코드에서 해당 정의를 사용할 수 있습니다. 예를 들어 example1 네임스페이스를 정의하면 다음 예제에서 볼 수 있는 것과 같이 example1을 특성으로 사용하여 myFunction() 메서드를 추가할 수 있습니다.

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

example1 네임스페이스를 특성으로 사용하여 myFunction() 메서드를 선언하면 이 메서드가 example1 네임스페이스에 속하게 됩니다.

네임스페이스를 적용할 때에는 다음 사항에 주의해야 합니다.

  • 각 선언에는 네임스페이스를 하나만 적용할 수 있습니다.

  • 한 번에 둘 이상의 정의에 네임스페이스 특성을 적용할 수 없습니다. 즉, 서로 다른 10개의 함수에 네임스페이스를 적용하려면 10개의 각 함수 정의에 네임스페이스를 특성으로 추가해야 합니다.

  • 또한 네임스페이스와 액세스 제어 지정자는 상호 배타적이므로 네임스페이스를 적용하는 경우 액세스 제어 지정자를 지정할 수 없습니다. 즉, 네임스페이스를 적용한 함수 또는 속성을 public, private, protected 또는 internal로 선언할 수 없습니다.

네임스페이스 참조

public, private, protected, internal 등의 액세스 제어 네임스페이스 중 하나로 선언된 메서드 또는 속성을 사용할 때 네임스페이스를 명시적으로 참조할 필요는 없습니다. 이러한 특수 네임스페이스에 대한 액세스는 컨텍스트에 의해 제어되기 때문입니다. 예를 들어 정의를 private 네임스페이스에 배치하면 자동으로 동일한 클래스 내의 코드에서 사용할 수 있게 됩니다. 그러나 사용자가 정의한 네임스페이스에는 이와 같은 컨텍스트 민감도가 없습니다. 사용자 정의 네임스페이스에 배치한 메서드 또는 속성을 사용하려면 네임스페이스를 참조해야 합니다.

use namespace 지시문을 사용하여 네임스페이스를 참조하거나, 이름 한정 기호(::)를 사용하여 네임스페이스로 이름을 정규화할 수 있습니다. use namespace 지시문을 사용하여 네임스페이스를 참조하면 네임스페이스가 "열려" 정규화되지 않은 모든 식별자에 해당 네임스페이스를 적용할 수 있습니다. 예를 들어 example1 네임스페이스를 정의한 경우 use namespace example1을 사용하여 해당 네임스페이스에 있는 이름에 액세스할 수 있습니다.

use namespace example1; 
myFunction();

한 번에 둘 이상의 네임스페이스를 열 수 있습니다. use namespace를 사용하여 네임스페이스를 열면 네임스페이스가 열린 코드 블록 전체에서 열린 상태로 남아 있게 됩니다. 열린 네임스페이스를 명시적으로 닫을 수는 없습니다.

그러나 둘 이상의 네임스페이스가 열려 있으면 이름이 충돌할 가능성이 커집니다. 네임스페이스를 열지 않으려면 use namespace 지시문을 사용하는 대신 네임스페이스 및 이름 한정 기호로 메서드 또는 속성 이름을 정규화하면 됩니다. 예를 들어 다음 코드에서는 example1 네임스페이스를 사용하여 myFunction()이라는 이름을 정규화하는 방법을 보여 줍니다.

example1::myFunction();

네임스페이스 사용

ActionScript 3.0의 일부인 flash.utils.Proxy 클래스에서 이름 충돌을 방지하는 데 사용되는 네임스페이스에 대한 실제 예를 찾아볼 수 있습니다. ActionScript 2.0의 Object.__resolve 속성을 대체하는 Proxy 클래스를 사용하면 정의되지 않은 속성 또는 메서드에 대한 참조를 차단하여 오류가 발생하는 것을 막을 수 있습니다. 이름이 충돌하지 않도록 하려면 Proxy 클래스의 메서드를 모두 flash_proxy 네임스페이스에 배치합니다.

flash_proxy 네임스페이스가 사용되는 방법을 보다 잘 이해하려면 Proxy 클래스를 사용하는 방법을 알아야 합니다. Proxy 클래스의 기능은 이 클래스에서 상속된 클래스에서만 사용할 수 있습니다. 즉, 객체에 Proxy 클래스의 메서드를 사용하려면 객체의 클래스 정의에서 Proxy 클래스를 확장해야 합니다. 예를 들어 정의되지 않은 메서드 호출을 차단하려면 Proxy 클래스를 확장한 다음 Proxy 클래스의 callProperty() 메서드를 재정의합니다.

네임스페이스 구현 과정은 일반적으로 네임스페이스 정의, 적용 및 참조의 3단계로 구성된다는 것을 기억하고 있을 것입니다. 그러나 Proxy 클래스의 어떤 메서드도 명시적으로 호출되지 않기 때문에 flash_proxy 네임스페이스는 정의 및 적용되기는 하지만 참조되지는 않습니다. ActionScript 3.0이 flash_proxy 네임스페이스를 정의하고 이를 Proxy 클래스에 적용합니다. 사용자가 작성하는 코드에서는 Proxy 클래스를 확장하는 클래스에 flash_proxy 네임스페이스를 적용하기만 하면 됩니다.

다음과 유사한 방식으로 flash_proxy 네임스페이스가 flash.utils 패키지에 정의되어 있습니다.

package flash.utils 
{ 
    public namespace flash_proxy; 
}

이 네임스페이스는 Proxy 클래스에서 발췌한 다음 예제에서 볼 수 있는 것과 같이 Proxy 클래스의 메서드에 적용됩니다.

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

다음 코드에서 볼 수 있는 것과 같이 먼저 Proxy 클래스와 flash_proxy 네임스페이스를 모두 가져와야 합니다. 그런 다음 Proxy 클래스를 확장하도록 클래스를 선언해야 하며, 엄격 모드에서 컴파일하는 경우에는 dynamic 특성도 추가해야 합니다. callProperty() 메서드를 재정의하는 경우 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); 
        } 
    } 
}

MyProxy 클래스의 인스턴스를 만들고 다음 예제에서 호출된 testing() 메서드처럼 정의되지 않은 메서드를 호출하는 경우, Proxy 객체에서 메서드 호출을 차단하고 재정의된 callProperty() 메서드 내의 명령문(이 경우 간단한 trace() 문)을 실행합니다.

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

flash_proxy 네임스페이스 내에 Proxy 클래스의 메서드를 배치하면 두 가지 장점이 있습니다. 첫 번째, 별도의 네임스페이스를 사용하면 Proxy 클래스를 확장하는 모든 클래스의 공용 인터페이스가 단순화됩니다. Proxy 클래스에서 재정의할 수 있는 메서드는 약 12개이며 모두 직접 호출되도록 설계되지 않았습니다. 공용 네임스페이스에 메서드를 모두 배치하면 혼동될 수 있습니다. 두 번째, Proxy의 하위 클래스에 Proxy 클래스의 메서드와 이름이 일치하는 인스턴스 메서드가 포함되어 있는 경우 flash_proxy 네임스페이스를 사용하면 이름 충돌이 방지됩니다. 예를 들어 사용자가 정의한 메서드 중 하나에 callProperty()라는 이름을 지정할 수 있습니다. 다음 코드에서는 사용자가 정의한 callProperty() 메서드가 다른 네임스페이스에 있으므로 오류가 발생하지 않습니다.

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

네임스페이스는 public, private, internalprotected와 같은 네 가지 액세스 제어 지정자로는 불가능한 방식으로 메서드 또는 속성에 대한 액세스를 제공하려는 경우에도 유용합니다. 예를 들어 몇 가지 유틸리티 메서드가 여러 패키지에 분산되어 있는 경우가 있을 수 있습니다. 이러한 메서드를 모든 패키지에서 사용할 수 있도록 하되 공용으로 지정하지 않으려고 합니다. 이렇게 하려면 네임스페이스를 만들어 사용자 고유의 특수 액세스 제어 지정자로 사용하면 됩니다.

다음 예제에서는 사용자 정의 네임스페이스를 사용하여 다른 패키지에 있는 두 개의 함수를 그룹화합니다. 동일한 네임스페이스로 함수를 그룹화하면 클래스 또는 패키지에서 use namespace 문을 한 번만 사용하여 두 함수를 참조하도록 할 수 있습니다.

이 예제에서는 네 개의 파일을 사용하여 이러한 기법을 설명합니다. 네 개의 파일 모두 클래스 경로에 있어야 합니다. 첫 번째 파일인 myInternal.as는 myInternal 네임스페이스를 정의하는 데 사용됩니다. 파일이 example 패키지에 있으므로 해당 파일을 example 폴더에 배치해야 합니다. 네임스페이스가 public으로 표시되어 있으므로 다른 패키지로 가져올 수 있습니다.

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

두 번째와 세 번째 파일인 Utility.as 및 Helper.as에서는 다른 패키지에서도 사용할 수 있어야 하는 메서드가 포함된 클래스를 정의합니다. Utility 클래스가 example.alpha 패키지에 있으므로 example 폴더의 하위 폴더인 alpha 폴더에 파일을 배치해야 합니다. Helper 클래스가 example.beta 패키지에 있으므로 example 폴더의 하위 폴더인 beta 폴더에 파일을 배치해야 합니다. 이러한 example.alpha 및 example.beta 패키지를 사용하려면 네임스페이스를 가져와야 합니다.

// 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; 
        } 
    } 
}

네 번째 파일인 NamespaceUseCase.as에는 기본 응용 프로그램 클래스가 정의되어 있으며 example 폴더와 상위 폴더가 같은 폴더에 있어야 합니다. Flash Professional에서 이 클래스는 FLA의 문서 클래스로 사용됩니다. NamespaceUseCase 클래스는 myInternal 네임스페이스를 가져와서 이를 사용하여 다른 패키지에 있는 두 개의 정적 메서드를 호출하기도 합니다. 예제에서는 코드를 단순화하기 위해서만 정적 메서드를 사용합니다. 정적 메서드와 인스턴스 메서드를 모두 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] 
        } 
    } 
}