클래스

클래스는 객체를 추상적으로 나타낸 것입니다. 클래스에는 객체에 담을 수 있는 데이터 유형 및 객체에 적용할 수 있는 비헤이비어에 대한 정보가 저장됩니다. 상호 작용하는 객체의 수가 적은 소규모 스크립트를 작성할 때는 이러한 추상화의 유용성이 잘 드러나지 않습니다. 그러나 프로그램의 범위가 커질수록 관리해야 하는 객체 수가 증가하기 마련입니다. 이러한 경우 클래스를 사용하면 객체가 만들어지는 방식 및 객체가 상호 작용하는 방식을 보다 효율적으로 제어할 수 있습니다.

ActionScript 1.0부터 ActionScript 프로그래머는 Function 객체를 사용하여 클래스와 유사한 구문을 만들 수 있었습니다. ActionScript 2.0에서는 classextends 등의 키워드를 통해 클래스가 공식적으로 지원되었습니다. ActionScript 3.0에서는 ActionScript 2.0에 도입된 키워드가 계속 지원될 뿐만 아니라 새로운 기능이 추가되었습니다. 예를 들어 protectedinternal 특성이 도입되어 ActionScript 3.0에서 액세스 제어가 향상되었습니다. 또한 finaloverride 키워드를 통해 상속을 보다 세밀히 제어할 수 있습니다.

ActionScript에서는 Java, C++ 또는 C# 등의 프로그래밍 언어로 클래스를 만든 경험이 있는 개발자에게 익숙한 환경을 제공합니다. class, extendspublic 등 다른 프로그래밍 언어에서와 동일한 키워드 및 특성 이름이 ActionScript에서 많이 사용됩니다.

참고: Adobe ActionScript 설명서에서 속성이라는 용어는 변수, 상수 및 메서드를 비롯하여 객체 또는 클래스의 멤버를 나타냅니다. 또한 클래스와 정적이라는 용어가 서로 구별되지 않고 사용되는 경우가 많지만 여기서는 이러한 용어가 서로 구별됩니다. 예를 들어 "클래스 속성"이라는 용어는 정적 멤버뿐만 아니라 클래스의 모든 멤버를 나타내는 데 사용됩니다.

클래스 정의

ActionScript 3.0 클래스 정의에는 ActionScript 2.0 클래스 정의와 비슷한 구문이 사용됩니다. 올바른 클래스 정의 구문에는 class 키워드 뒤에 클래스 이름이 나옵니다. 클래스 이름 뒤에는 중괄호({})로 묶인 클래스 본문이 나옵니다. 예를 들어 다음 코드에서는 visible이라는 변수 하나가 들어 있는 Shape라는 클래스가 만들어집니다.

public class Shape 
{ 
    var visible:Boolean = true; 
}

중요한 구문 변경 내용 중 하나는 패키지 안에 있는 클래스의 정의와 관련된 것입니다. ActionScript 2.0에서는 클래스가 패키지 안에 있는 경우 클래스 선언에 패키지 이름이 포함되어야 합니다. ActionScript 3.0에서는 package 문이 도입되어, 패키지 이름이 클래스 선언이 아닌 패키지 선언에 포함되어야 합니다. 예를 들어 다음 클래스 선언에서는 flash.display 패키지에 속한 BitmapData 클래스가 ActionScript 2.0과 ActionScript 3.0에서 정의된 방식을 볼 수 있습니다.

// ActionScript 2.0 
class flash.display.BitmapData {} 
 
// ActionScript 3.0 
package flash.display 
{ 
    public class BitmapData {} 
}

클래스 특성

ActionScript 3.0에서는 다음 네 가지 특성 중 하나를 사용하여 클래스 정의를 수정할 수 있습니다.

특성

정의

dynamic

런타임에 속성을 인스턴스에 추가할 수 있게 합니다.

final

다른 클래스에서 확장할 수 없습니다.

internal(기본값)

현재 패키지 내에서 참조할 수 있습니다.

public

모든 위치에서 참조할 수 있습니다.

internal의 경우를 제외하고 이러한 각 특성에 연결된 비헤이비어를 사용하려면 특성을 명시적으로 포함합니다. 예를 들어 클래스를 정의할 때 dynamic 특성을 포함하지 않으면 런타임에 속성을 클래스 인스턴스에 추가할 수 없습니다. 특성을 명시적으로 지정하려면 다음 코드와 같이 클래스 정의 시작 부분에 특성을 배치합니다.

dynamic class Shape {}

abstract라는 특성은 이 목록에 포함되어 있지 않습니다. ActionScript 3.0에서 추상 클래스는 지원되지 않습니다. privateprotected라는 특성도 목록에 포함되어 있지 않습니다. 이러한 특성은 클래스 정의 내에서만 의미가 있으며 클래스 자체에는 적용할 수 없습니다. 패키지 외부에서 클래스를 공용으로 참조할 수 없게 하려면 클래스를 패키지 내에 배치하고 클래스에 internal 특성을 지정합니다. 또는 internalpublic 특성을 모두 생략하여 컴파일러에서 자동으로 internal 특성을 추가하도록 합니다. 클래스가 정의된 소스 파일 외부에서 해당 클래스를 참조할 수 없도록 클래스를 정의할 수도 있습니다. 이렇게 하려면 클래스를 소스 파일 맨 아래에서 패키지 정의의 닫는 중괄호 밑에 배치합니다.

클래스 본문

클래스 본문은 중괄호로 묶이며 클래스의 변수, 상수 및 메서드를 정의합니다. 다음 예제에서는 ActionScript 3.0의 Accessibility 클래스 선언을 보여 줍니다.

public final class Accessibility 
{ 
    public static function get active():Boolean; 
    public static function updateProperties():void; 
}

클래스 본문 내에 네임스페이스를 정의할 수도 있습니다. 다음 예제에서는 클래스 본문 내에 네임스페이스를 정의하여 해당 클래스에서 메서드의 특성으로 사용하는 방법을 보여 줍니다.

public class SampleClass 
{ 
    public namespace sampleNamespace; 
    sampleNamespace function doSomething():void; 
}

ActionScript 3.0에서는 클래스 본문 내에 정의뿐만 아니라 명령문도 포함시킬 수 있습니다. 클래스 본문 내에 있지만 메서드 정의 외부에 있는 명령문은 정확히 한 번만 실행됩니다. 이 명령문의 실행은 클래스 정의가 처음 발견되고 관련 클래스 객체가 만들어질 때 이루어집니다. 다음 예제에는 외부 함수인 hello()에 대한 호출과 클래스가 정의될 때 확인 메시지를 출력하는 trace 문이 포함되어 있습니다.

function hello():String 
{ 
    trace("hola"); 
} 
class SampleClass 
{ 
    hello(); 
    trace("class created"); 
} 
// output when class is created 
hola 
class created

ActionScript 3.0에서는 같은 클래스 본문 내에서 이름이 같은 정적 속성과 인스턴스 속성을 정의할 수 있습니다. 예를 들어 다음 코드에서는 message라는 정적 변수 및 이름이 같은 인스턴스 변수를 선언합니다.

class StaticTest 
{ 
    static var message:String = "static variable"; 
    var message:String = "instance variable"; 
} 
// In your script 
var myST:StaticTest = new StaticTest(); 
trace(StaticTest.message); // output: static variable 
trace(myST.message); // output: instance variable

클래스 속성 특성

ActionScript 객체 모델에서 속성이라는 용어는 변수, 상수 및 메서드 등 클래스의 멤버가 될 수 있는 모든 항목을 나타냅니다. 그러나 Adobe ActionScript 3.0 Reference for the Adobe Flash Platform에서 이 용어는 보다 좁은 의미로 사용됩니다. 이 컨텍스트에서 속성이라는 용어는 변수이거나 getter 또는 setter 메서드에 의해 정의되는 클래스 멤버만 나타냅니다. ActionScript 3.0에는 클래스의 모든 속성과 함께 사용할 수 있는 특성 집합이 있습니다. 다음 표에 이러한 특성들이 나열되어 있습니다.

특성

정의

internal(기본값)

같은 패키지 내에서 참조할 수 있습니다.

private

같은 클래스에서 참조할 수 있습니다.

protected

같은 클래스 및 파생 클래스에서 참조할 수 있습니다.

public

모든 위치에서 참조할 수 있습니다.

static

속성이 클래스의 인스턴스가 아니라 클래스에 속하도록 지정합니다.

UserDefinedNamespace

사용자 정의 네임스페이스 이름입니다.

액세스 제어 네임스페이스 특성

ActionScript 3.0에서는 클래스 내에 정의된 속성에 대한 액세스를 제어하는 네 가지 특수 특성인 public, private, protectedinternal이 제공됩니다.

public 특성을 사용하면 스크립트의 모든 위치에서 속성을 참조할 수 있습니다. 예를 들어 해당 패키지 외부의 코드에서 메서드를 사용할 수 있게 하려면 메서드를 public 특성으로 선언해야 합니다. 이는 var, const 또는 function 등 속성을 정의하는 데 사용된 키워드에 관계없이 모든 속성에서 마찬가지입니다.

private 특성을 사용하면 해당 속성이 정의된 클래스 내에서만 속성에 액세스할 수 있습니다. 이 private 특성의 비헤이비어는 ActionScript 2.0에서 하위 클래스가 수퍼 클래스의 전용 속성에 액세스하도록 허용했던 비헤이비어와는 다릅니다. 또한 런타임 액세스 비헤이비어에도 중요한 차이점이 있습니다. ActionScript 2.0에서는 private 키워드를 사용하면 컴파일 타임에만 액세스가 금지되었고 런타임에는 이러한 제한을 쉽게 피할 수 있었습니다. ActionScript 3.0에서는 더 이상 그렇지 않습니다. private으로 표시된 속성은 컴파일 타임과 런타임 시 모두 사용할 수 없습니다.

예를 들어 다음 코드에서는 전용 변수 하나가 있는 PrivateExample이라는 간단한 클래스를 만든 다음 클래스 외부에서 전용 변수에 액세스합니다.

class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this is a run-time error. 

ActionScript 3.0의 경우 myExample.privVar과 같이 도트 연산자를 사용하여 전용 속성에 액세스하려고 하면 엄격 모드를 사용하는 경우 컴파일 타임 오류가 발생합니다. 그렇지 않은 경우에는 myExample["privVar"]과 같이 속성 액세스 연산자를 사용한 경우처럼 런타임에 오류가 보고됩니다.

다음 표에서는 동적이 아닌 봉인 클래스에 속한 전용 속성에 액세스한 결과를 보여 줍니다.

 

엄격 모드

표준 모드

도트 연산자(.)

컴파일 타임 오류

런타임 오류

대괄호 연산자([])

런타임 오류

런타임 오류

dynamic 특성으로 선언된 클래스의 경우에는 전용 변수에 액세스해도 런타임 오류가 발생하지 않습니다. 대신 값을 참조할 수 없으므로 undefined 값이 반환됩니다. 그러나 엄격 모드에서 도트 연산자를 사용하면 컴파일 타임 오류가 발생합니다. 다음 예제는 이전 예제와 동일하지만 PrivateExample 클래스가 동적 클래스로 선언됩니다.

dynamic class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // output: undefined

동적 클래스를 사용하면 클래스 외부 코드에서 전용 속성에 액세스할 때 일반적으로 오류가 발생하는 대신 undefined 값이 반환됩니다. 다음 표를 보면 엄격 모드에서 도트 연산자를 사용하여 전용 속성에 액세스할 때만 오류가 발생함을 알 수 있습니다.

 

엄격 모드

표준 모드

도트 연산자(.)

컴파일 타임 오류

undefined

대괄호 연산자([])

undefined

undefined

ActionScript 3.0에서 새로 도입된 protected 특성을 사용하면 자체 클래스나 하위 클래스에서 속성에 액세스할 수 있습니다. 즉, protected 속성은 자체 클래스 내에서 또는 상속 계층 구조에서 해당 클래스 아래쪽에 있는 모든 클래스에서 사용할 수 있습니다. 하위 클래스가 수퍼 클래스와 같은 패키지에 있는지 또는 다른 패키지에 있는지에 관계없이 하위 클래스에서 protected 속성을 사용할 수 있습니다.

ActionScript 2.0에 익숙한 사용자에게 이 기능은 ActionScript 2.0의 private 특성과 비슷하고, ActionScript 3.0의 protected 특성은 Java의 protected 특성과 비슷합니다. 그러나 Java 버전의 경우 같은 패키지 내에 있는 호출자에도 액세스할 수 있다는 차이점이 있습니다. protected 특성은 하위 클래스에 필요한 변수 또는 메서드를 상속 체인 외부에 있는 코드로부터 숨기려는 경우에 유용합니다.

ActionScript 3.0에서 새로 도입된 internal 특성을 사용하면 자체 패키지 내에서 속성을 호출할 수 있습니다. 이는 패키지 안에 있는 코드의 기본 특성이며 다음 특성이 지정되지 않은 모든 속성에 적용됩니다.

  • public

  • private

  • protected

  • 사용자 정의 네임스페이스

internal 특성은 Java의 기본 액세스 제어와 비슷하지만 Java의 경우에는 이 액세스 수준에 명시적으로 지정된 이름이 없으며 이 액세스 수준을 사용하려면 다른 액세스 수식어를 모두 생략해야 합니다. ActionScript 3.0에서 internal 특성을 사용하면 자체 패키지 내에서만 속성을 호출하도록 하려는 의도를 명시적으로 나타낼 수 있습니다.

static 특성

var, const 또는 function 키워드로 선언된 속성에 사용할 수 있는 static 특성을 통해 속성을 클래스의 인스턴스가 아닌 클래스 자체에 연결할 수 있습니다. 클래스 외부의 코드에서 정적 속성을 호출하려면 인스턴스 이름 대신 클래스 이름을 사용해야 합니다.

정적 속성은 하위 클래스로 상속되지는 않지만 하위 클래스의 범위 체인에 포함됩니다. 즉, 하위 클래스의 본문 내에서는 정적 변수 또는 메서드가 정의된 클래스를 참조하지 않고도 해당 변수 또는 메서드를 사용할 수 있습니다.

사용자 정의 네임스페이스 특성

미리 정의된 액세스 제어 특성을 사용하는 대신 사용자 정의 네임스페이스를 만들어 특성으로 사용할 수 있습니다. 네임스페이스 특성은 정의마다 하나만 사용할 수 있으며 액세스 제어 특성(public, private, protected, internal)과는 함께 사용할 수 없습니다.

변수

변수는 var 또는 const 키워드로 선언할 수 있습니다. var 키워드로 선언된 변수의 값은 스크립트 실행 중 여러 차례 변경될 수 있습니다. const 키워드로 선언된 변수는 상수라고 하며, 값을 한 번만 지정할 수 있습니다. 초기화된 상수에 새 값을 지정하려고 하면 오류가 발생합니다.

정적 변수

정적 변수는 static 키워드를 var 또는 const 문 중 하나와 조합하여 선언합니다. 정적 변수는 클래스의 인스턴스가 아닌 클래스 자체에 연결되며, 객체의 전체 클래스에 적용되는 정보를 저장 및 공유하는 데 유용합니다. 예를 들어 클래스가 인스턴스화된 횟수를 집계하거나 클래스 인스턴스의 최대 개수를 저장하려는 경우에 정적 변수가 적합합니다.

다음 예제에서는 totalCount 변수를 만들어 클래스 인스턴스화 횟수를 추적하고 MAX_NUM 상수를 만들어 인스턴스화 최대 횟수를 저장합니다. totalCountMAX_NUM 변수는 특정 인스턴스가 아닌 전체 클래스에 적용되는 값을 포함하므로 정적 변수입니다.

class StaticVars 
{ 
    public static var totalCount:int = 0; 
    public static const MAX_NUM:uint = 16; 
}

StaticVars 클래스의 외부에 있는 코드나 하위 클래스에 있는 코드에서는 클래스 자체를 통해서만 totalCountMAX_NUM 속성을 참조할 수 있습니다. 예를 들어 다음 코드를 사용해야 합니다.

trace(StaticVars.totalCount); // output: 0 
trace(StaticVars.MAX_NUM); // output: 16

클래스 인스턴스를 통해서는 정적 변수에 액세스할 수 없으므로 다음 코드에서는 오류가 반환됩니다.

var myStaticVars:StaticVars = new StaticVars(); 
trace(myStaticVars.totalCount); // error 
trace(myStaticVars.MAX_NUM); // error

staticconst 키워드를 모두 사용하여 선언한 변수는 StaticVars 클래스에서 MAX_NUM의 경우와 같이 상수를 선언함과 동시에 초기화해야 합니다. 생성자나 인스턴스 메서드 내에서는 MAX_NUM에 값을 지정할 수 없습니다. 다음 코드에서는 정적 상수를 제대로 초기화하지 않았으므로 오류가 발생합니다.

// !! Error to initialize static constant this way 
class StaticVars2 
{ 
    public static const UNIQUESORT:uint; 
    function initializeStatic():void 
    { 
        UNIQUESORT = 16; 
    } 
}

인스턴스 변수

인스턴스 변수에는 static 키워드 없이 varconst 키워드로 선언된 속성이 포함됩니다. 인스턴스 변수는 전체 클래스가 아닌 클래스 인스턴스에 연결되며 인스턴스에 고유한 값을 저장하는 데 유용합니다. 예를 들어 Array 클래스에는 Array 클래스의 특정 인스턴스에 들어 있는 배열 요소의 수가 저장되는 length라는 인스턴스 속성이 있습니다.

인스턴스 변수는 var 또는 const 등 선언된 방식에 관계없이 하위 클래스에서 재정의할 수 없습니다. 그러나 getter 및 setter 메서드를 재정의하면 변수를 재정의하는 것과 비슷한 결과를 달성할 수 있습니다.

메서드

메서드는 클래스 정의에 포함되는 함수입니다. 클래스의 인스턴스를 만들면 해당 인스턴스에 메서드가 바인딩됩니다. 클래스 외부에 정의된 함수와 달리 메서드는 자신이 연결된 인스턴스와 분리하여 사용될 수 없습니다.

메서드는 function 키워드를 사용하여 정의됩니다. 모든 클래스 속성과 마찬가지로 private, protected, public, internal, static 등의 클래스 속성 특성이나 사용자 정의 네임스페이스를 메서드에 적용할 수 있습니다. 함수 명령문은 다음과 같이 사용할 수 있습니다.

public function sampleFunction():String {}

다음과 같이 함수 표현식이 지정된 변수를 사용할 수도 있습니다.

public var sampleFunction:Function = function () {}

대부분의 경우에는 다음과 같은 이유로 인해 함수 표현식 대신 함수 명령문을 사용합니다.

  • 함수 명령문은 보다 간결하고 쉽게 읽을 수 있습니다.

  • 함수 명령문을 통해 overridefinal 키워드를 사용할 수 있습니다.

  • 함수 명령문을 사용하면 식별자(함수 이름)와 메서드 본문 내의 코드가 보다 견고하게 결합됩니다. 대입문을 사용하면 변수 값을 변경할 수 있으므로 변수와 해당 함수 표현식 간의 연결은 언제든지 끊어질 수 있습니다. 변수를 var 대신 const로 선언하면 이 문제를 해결할 수는 있지만 코드를 읽기 어려워지고 overridefinal 키워드를 사용할 수 없게 되므로 이는 좋은 방법이 아닙니다.

프로토타입 객체에 함수를 연결하려는 경우에는 함수 표현식을 사용해야 합니다.

생성자 메서드

생성자라고도 하는 생성자 메서드는 해당 메서드가 정의된 클래스와 이름이 같은 함수입니다. 생성자 메서드에 포함된 코드는 new 키워드를 사용하여 클래스의 인스턴스를 만들 때마다 실행됩니다. 예를 들어 다음 코드에서는 status라는 속성 하나가 들어 있는 Example이라는 간단한 클래스를 정의합니다. status 변수의 초기값은 생성자 함수 안에서 설정됩니다.

class Example 
{ 
    public var status:String; 
    public function Example() 
    { 
        status = "initialized"; 
    } 
} 
 
var myExample:Example = new Example(); 
trace(myExample.status); // output: initialized

생성자 메서드는 항상 공용이지만 public 특성은 생략할 수 있습니다. 생성자에서는 private, protected 또는 internal 등의 다른 액세스 제어 지정자를 사용할 수 없습니다. 또한 생성자 메서드에는 사용자 정의 네임스페이스를 사용할 수 없습니다.

생성자에서는 super() 문을 사용하여 바로 위 수퍼 클래스의 생성자를 명시적으로 호출할 수 있습니다. 수퍼 클래스 생성자를 명시적으로 호출하지 않으면 컴파일러에서 생성자 본문의 첫 명령문 앞에 자동으로 호출을 삽입합니다. super 접두어로 수퍼 클래스를 참조하여 수퍼 클래스의 메서드를 호출할 수도 있습니다. 같은 생성자 본문에서 super()super를 함께 사용하려는 경우 super()를 먼저 호출해야 합니다. 그렇지 않으면 super 참조가 정상적으로 작동하지 않습니다. 또한 throw 또는 return 문을 사용하기 전에 super() 생성자를 호출해야 합니다.

다음 예제를 통해 super() 생성자를 호출하기 전에 super 참조를 사용한 결과를 확인해 볼 수 있습니다. 새 클래스인 ExampleEx에서는 Example 클래스를 확장합니다. ExampleEx 생성자에서 super()를 호출하기 전에 수퍼 클래스에 정의된 status 변수에 액세스합니다. 이 경우 super() 생성자가 실행되기 전에는 status 변수를 사용할 수 없으므로 ExampleEx 생성자 내의 trace() 문에서 null 값을 출력합니다.

class ExampleEx extends Example 
{ 
    public function ExampleEx() 
    { 
        trace(super.status); 
        super(); 
    } 
} 
 
var mySample:ExampleEx = new ExampleEx(); // output: null

생성자 내에서도 return 문을 사용할 수 있지만 값을 반환할 수는 없습니다. 즉, return 문에 표현식이나 값을 연결하면 안 됩니다. 따라서 생성자 메서드는 값을 반환할 수 없으며 반환 유형을 지정할 수 없습니다.

클래스에 생성자 메서드를 정의하지 않으면 컴파일러에서 자동으로 빈 생성자를 만듭니다. 클래스에서 다른 클래스를 확장하는 경우에는 컴파일러에서 자동으로 생성되는 생성자에 super() 호출이 포함됩니다.

정적 메서드

클래스 메서드라고도 하는 정적 메서드는 static 키워드로 선언되는 메서드입니다. 정적 메서드는 클래스 인스턴스가 아닌 클래스 자체에 연결되며, 개별 인스턴스가 아닌 전체적인 상태에 영향을 주는 기능을 캡슐화하는 데 유용합니다. 정적 메서드는 전체 클래스에 연결되므로 클래스의 인스턴스가 아닌 클래스를 통해서만 액세스할 수 있습니다.

정적 메서드는 클래스 인스턴스의 상태에 영향을 주는 데 국한되지 않는 기능을 캡슐화하는 데 유용합니다. 즉, 클래스 인스턴스의 값에 직접 영향을 주지 않는 기능을 제공하는 메서드는 정적 메서드로 선언해야 합니다. 예를 들어 Date 클래스에는 문자열을 받아 숫자로 변환하는 parse()라는 정적 메서드가 있습니다. 이 메서드는 클래스의 개별 인스턴스에 영향을 주지 않으므로 정적입니다. 대신 parse() 메서드는 날짜 값을 나타내는 문자열을 받아 파싱하여 Date 객체의 내부 표현과 호환되는 형식으로 숫자를 반환합니다. 이 메서드는 Date 클래스의 인스턴스에 직접 적용되지 않으므로 인스턴스 메서드가 아닙니다.

정적 parse() 메서드는 Date 클래스에 속하는 getMonth() 등의 인스턴스 메서드와 대조됩니다. getMonth() 메서드는 Date 인스턴스의 월을 나타내는 특정 구성 요소를 검색하여 인스턴스의 값에 직접 작용하므로 인스턴스 메서드입니다.

정적 메서드는 개별 인스턴스에 바인딩되지 않으므로 정적 메서드 본문 내에서는 this 또는 super 키워드를 사용할 수 없습니다. this 참조와 super 참조는 인스턴스 메서드의 컨텍스트 내에서만 의미가 있습니다.

몇 가지 다른 클래스 기반 프로그래밍 언어와 달리 ActionScript 3.0에서는 정적 메서드가 상속되지 않습니다.

인스턴스 메서드

인스턴스 메서드는 static 키워드 없이 선언된 메서드입니다. 인스턴스 메서드는 전체 클래스가 아닌 클래스 인스턴스에 연결되며, 클래스의 개별 인스턴스에 영향을 주는 기능을 구현하는 데 유용합니다. 예를 들어 Array 클래스에는 Array 인스턴스에 직접 작용하는 sort()라는 인스턴스 메서드가 있습니다.

인스턴스 메서드 본문 내에서는 정적 변수와 인스턴스 변수가 모두 범위에 포함되므로 간단한 식별자를 사용하여 같은 클래스에 정의된 해당 변수를 참조할 수 있습니다. 예를 들어 다음 CustomArray 클래스에서는 Array 클래스를 확장합니다. CustomArray 클래스에는 클래스 인스턴스의 총 개수를 추적하는 arrayCountTotal이라는 정적 변수, 인스턴스가 작성된 순서를 추적하는 arrayNumber라는 인스턴스 변수 및 이러한 변수의 값을 반환하는 getPosition()이라는 인스턴스 메서드가 정의됩니다.

public class CustomArray extends Array 
{ 
    public static var arrayCountTotal:int = 0; 
    public var arrayNumber:int; 
 
    public function CustomArray() 
    { 
        arrayNumber = ++arrayCountTotal; 
    } 
     
    public function getArrayPosition():String 
    { 
         return ("Array " + arrayNumber + " of " + arrayCountTotal); 
    } 
}

클래스 외부의 코드에서는 CustomArray.arrayCountTotal과 같이 클래스 객체를 통해 정적 변수 arrayCountTotal을 액세스해야 하지만, getPosition() 메서드 본문 내에 있는 코드에서는 정적 변수 arrayCountTotal을 직접 참조할 수 있습니다. 이는 수퍼 클래스에 있는 정적 변수의 경우에도 마찬가지입니다. ActionScript 3.0에서는 정적 속성이 상속되지 않지만 수퍼 클래스의 정적 속성은 범위에 포함됩니다. 예를 들어 Array 클래스에는 DESCENDING이라는 상수를 비롯한 몇 가지 정적 변수가 있습니다. Array의 하위 클래스에 있는 코드에서는 간단한 식별자를 사용하여 정적 상수 DESCENDING에 액세스할 수 있습니다.

public class CustomArray extends Array 
{ 
    public function testStatic():void 
    { 
        trace(DESCENDING); // output: 2 
    } 
}

인스턴스 메서드의 본문 내에서 this 참조의 값은 해당 메서드가 연결된 인스턴스에 대한 참조입니다. 다음 코드에서는 this 참조가 해당 메서드가 포함된 인스턴스를 가리킴을 보여 줍니다.

class ThisTest 
{ 
    function thisValue():ThisTest 
    { 
        return this; 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
trace(myTest.thisValue() == myTest); // output: true

인스턴스 메서드의 상속은 overridefinal 키워드를 통해 제어할 수 있습니다. 상속된 메서드를 다시 정의하려면 override 특성을 사용하고, 하위 클래스에서 메서드를 재정의할 수 없게 하려면 final 특성을 사용합니다.

get 및 set 접근자 메서드

gettersetter라고도 하는 get 및 set 접근자 함수를 통해 정보 은폐 및 캡슐화라는 프로그래밍 원칙을 준수하면서 클래스에 사용하기 쉬운 프로그래밍 인터페이스를 제공할 수 있습니다. get 및 set 함수를 사용하면 클래스 속성을 클래스 전용으로 유지하면서 클래스 사용자가 클래스 메서드를 호출하는 대신 클래스 변수에 액세스하는 것처럼 이러한 속성에 액세스하도록 허용할 수 있습니다.

이러한 방법을 사용하면 getPropertyName()setPropertyName() 등 이름이 복잡한 기존 접근자 함수를 사용하지 않아도 된다는 장점이 있습니다. 또한 읽기 및 쓰기 액세스가 모두 허용되는 속성마다 두 개의 공용 함수를 만들지 않아도 됩니다.

GetSet이라는 다음 예제 클래스에는 privateProperty라는 전용 변수에 대한 액세스를 제공하는 publicAccess()라는 get 및 set 접근자 함수가 있습니다.

class GetSet 
{ 
    private var privateProperty:String; 
     
    public function get publicAccess():String 
    { 
        return privateProperty; 
    } 
     
    public function set publicAccess(setValue:String):void 
    { 
        privateProperty = setValue; 
    } 
}

다음과 같이 privateProperty 속성에 직접 액세스하려고 하면 오류가 발생합니다.

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.privateProperty); // error occurs

GetSet 클래스 사용자는 속성처럼 보이는 publicAccess라는 항목을 대신 사용하게 되지만, 실제로 이는 privateProperty라는 전용 속성에 작용하는 get 및 set 접근자 함수 쌍입니다. 다음 예제에서는 GetSet 클래스를 인스턴스화한 다음 publicAccess라는 공용 접근자를 사용하여 privateProperty의 값을 설정합니다.

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.publicAccess); // output: null 
myGetSet.publicAccess = "hello"; 
trace(myGetSet.publicAccess); // output: hello

getter 및 setter 함수를 사용하여 수퍼 클래스에서 상속된 속성을 재정의할 수도 있습니다. 일반적인 클래스 멤버 변수를 사용할 때는 이러한 작업이 불가능합니다. var 키워드로 선언된 클래스 멤버 변수는 하위 클래스에서 재정의할 수 없습니다. 그러나 getter 및 setter 함수를 사용하여 만든 속성에는 이러한 제한이 없습니다. 수퍼 클래스에서 상속된 getter 및 setter 함수에 override 특성을 사용할 수 있습니다.

바인딩된 메서드

메서드 클로저라고도 하는 바인딩된 메서드는 해당 인스턴스에서 추출된 메서드입니다. 바인딩된 메서드의 예로는 함수에 인수로 전달된 메서드 또는 함수에서 값으로 반환된 메서드가 있습니다. ActionScript 3.0에 새로 도입된 바인딩된 메서드는 인스턴스에서 추출되어도 의미상의 환경이 유지된다는 점에서 함수 클로저와 비슷합니다. 그러나 바인딩된 메서드에서는 this 참조가 해당 메서드를 구현하는 인스턴스에 연결된 상태로 유지된다는 점에서 함수 클로저와 다릅니다. 즉, 바인딩된 메서드의 this 참조는 항상 메서드를 구현한 원래 객체를 가리킵니다. 함수 클로저의 경우에는 this 참조가 일반적이므로 호출 시점에서 함수에 연결된 객체를 가리킵니다.

this 키워드를 사용하는 경우 바인딩된 메서드를 잘 이해해야 합니다. this 키워드는 메서드의 부모 객체를 참조합니다. 대부분의 ActionScript 프로그래머는 this 키워드가 항상 메서드 정의가 들어 있는 객체 또는 클래스를 나타낸다고 예상합니다. 그러나 메서드 바인딩을 사용하지 않으면 그렇지 않을 수도 있습니다. 예를 들어 이전 버전의 ActionScript에서는 this 참조가 메서드를 구현한 인스턴스를 참조하지 않을 수도 있었습니다. ActionScript 2.0의 경우 인스턴스에서 메서드를 추출하면 this 참조가 원래 인스턴스에 바인딩되지 않을 뿐만 아니라 인스턴스 클래스의 멤버 변수 및 메서드를 사용할 수 없습니다. ActionScript 3.0에서는 메서드를 매개 변수로 전달할 때 바인딩된 메서드가 자동으로 만들어지므로 이러한 문제가 없습니다. 바인딩된 메서드를 사용하면 this 키워드가 항상 메서드가 정의된 객체 또는 클래스를 참조하게 됩니다.

다음 코드에서는 ThisTest라는 클래스를 정의합니다. 이 클래스에는 바인딩된 메서드를 정의하는 foo()라는 메서드 및 바인딩된 메서드를 반환하는 bar()라는 메서드가 있습니다. 클래스 외부에 있는 코드에서는 ThisTest 클래스의 인스턴스를 만들고 bar() 메서드를 호출한 다음 반환 값을 myFunc라는 변수에 저장합니다.

class ThisTest 
{ 
    private var num:Number = 3; 
    function foo():void // bound method defined 
    { 
        trace("foo's this: " + this); 
        trace("num: " + num); 
    } 
    function bar():Function 
    { 
        return foo; // bound method returned 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
var myFunc:Function = myTest.bar(); 
trace(this); // output: [object global] 
myFunc(); 
/* output:  
foo's this: [object ThisTest] 
output: num: 3 */

코드의 마지막 두 행을 보면 this 참조는 전역 객체를 가리키지만 바인딩된 메서드인 foo()this 참조는 계속 ThisTest 클래스를 가리키는 것을 알 수 있습니다. 또한 myFunc 변수에 저장된 바인딩된 메서드에서는 ThisTest 클래스의 멤버 변수에 계속 액세스할 수 있습니다. 이 코드를 ActionScript 2.0에서 실행하면 this 참조가 서로 일치하게 되고 num 변수는 undefined가 됩니다.

바인딩된 메서드를 사용하는 것이 특히 유용한 부분은 이벤트 핸들러입니다. addEventListener() 메서드에는 함수 또는 메서드를 인수로 전달해야 하기 때문입니다.

클래스와 열거형

열거형은 소규모 값 집합을 캡슐화하기 위해 만드는 사용자 정의 데이터 유형입니다. ActionScript 3.0에서는 C++의 enum 키워드나 Java의 Enumeration 인터페이스와 같은 구체적인 열거형 기능이 지원되지 않습니다. 그러나 클래스와 정적 상수를 사용하여 열거형을 만들 수 있습니다. 예를 들어 ActionScript 3.0의 PrintJob 클래스에서는 다음 코드와 같이 PrintJobOrientation이라는 열거형을 사용하여 값 "landscape""portrait"를 저장합니다.

public final class PrintJobOrientation 
{ 
    public static const LANDSCAPE:String = "landscape"; 
    public static const PORTRAIT:String = "portrait"; 
}

열거형 클래스는 확장할 필요가 없으므로 관습적으로 final 특성으로 선언됩니다. 이러한 클래스는 정적 멤버만 포함하므로 클래스의 인스턴스를 만들 수 없습니다. 대신 다음 인용 코드와 같이 클래스 객체를 직접 사용하여 열거형 값에 액세스합니다.

var pj:PrintJob = new PrintJob(); 
if(pj.start()) 
{ 
    if (pj.orientation == PrintJobOrientation.PORTRAIT) 
    { 
        ... 
    } 
    ... 
}

ActionScript 3.0의 모든 열거형 클래스에는 String, int 또는 uint 유형의 변수만 들어 있습니다. 리터럴 문자열이나 숫자 값 대신 열거형을 사용하면 철자를 잘못 입력한 오류를 쉽게 찾을 수 있다는 장점이 있습니다. 열거형의 이름을 잘못 입력하면 ActionScript 컴파일러에서 오류가 발생합니다. 리터럴 값을 사용하면 단어의 철자를 잘못 입력하거나 숫자를 잘못 입력해도 컴파일러에서 메시지가 표시되지 않습니다. 이전 예제의 경우 다음 인용 코드와 같이 열거형 상수 이름을 잘못 입력하면 컴파일러에서 오류가 발생합니다.

    if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error

그러나 다음과 같이 문자열 리터럴 값을 잘못 입력한 경우에는 컴파일러에서 오류가 발생하지 않습니다.

    if (pj.orientation == "portrai") // no compiler error

열거형을 만드는 두 번째 방법에서도 열거형에 사용할 정적 속성이 있는 별도의 클래스를 만듭니다. 그러나 두 번째 방법은 각 정적 속성에 문자열 또는 정수 값 대신 클래스 인스턴스가 포함된다는 점이 다릅니다. 예를 들어 다음 코드에서는 요일에 대한 열거형 클래스를 만듭니다.

public final class Day 
{ 
    public static const MONDAY:Day = new Day(); 
    public static const TUESDAY:Day = new Day(); 
    public static const WEDNESDAY:Day = new Day(); 
    public static const THURSDAY:Day = new Day(); 
    public static const FRIDAY:Day = new Day(); 
    public static const SATURDAY:Day = new Day(); 
    public static const SUNDAY:Day = new Day(); 
}

ActionScript 3.0에는 이 기술이 사용되지 않지만, 이 기술을 통해 제공되는 향상된 유형 확인을 선호하는 많은 개발자는 이 기술을 사용하고 있습니다. 예를 들어 열거형 값을 반환하는 메서드에서는 반환 값을 열거형 데이터 유형으로 제한할 수 있습니다. 다음 코드에서는 요일을 반환하는 함수뿐만 아니라 열거형을 유형 약어로 사용하는 함수 호출도 보여 줍니다.

function getDay():Day 
{ 
    var date:Date = new Date(); 
    var retDay:Day; 
    switch (date.day) 
    { 
        case 0: 
            retDay = Day.MONDAY; 
            break; 
        case 1: 
            retDay = Day.TUESDAY; 
            break; 
        case 2: 
            retDay = Day.WEDNESDAY; 
            break; 
        case 3: 
            retDay = Day.THURSDAY; 
            break; 
        case 4: 
            retDay = Day.FRIDAY; 
            break; 
        case 5: 
            retDay = Day.SATURDAY; 
            break; 
        case 6: 
            retDay = Day.SUNDAY; 
            break; 
    } 
    return retDay; 
} 
 
var dayOfWeek:Day = getDay();

Day 클래스를 개선하여 각 요일을 정수에 연결하고 문자열로 나타낸 요일을 반환하는 toString() 메서드를 제공할 수도 있습니다.

포함된 에셋 클래스

ActionScript 3.0에서는 포함된 에셋 클래스라는 특수 클래스를 사용하여 포함된 에셋을 나타냅니다. 포함된 에셋은 컴파일 타임에 SWF 파일에 포함된 사운드, 이미지 또는 글꼴 등의 에셋입니다. 에셋을 동적으로 로드하지 않고 에셋을 포함하면 런타임에 항상 에셋을 사용할 수 있다는 장점이 있지만 SWF 파일 크기가 증가하는 단점이 있습니다.

Flash Professional에서 포함된 에셋 클래스 사용

에셋을 포함하려면 먼저 FLA 파일의 라이브러리에 에셋을 배치합니다. 그런 다음 에셋의 링크 속성을 사용하여 포함된 에셋 클래스에 이름을 지정합니다. 이 이름을 가진 클래스가 클래스 경로에 없는 경우 사용자가 지정한 이름의 에셋이 자동으로 생성됩니다. 그런 다음 포함된 에셋 클래스의 인스턴스를 만든 후, 이 클래스에 의해 정의되거나 상속된 속성 및 메서드를 사용합니다. 예를 들어 다음과 같은 코드를 사용하면 포함된 에셋 클래스 PianoMusic에 연결된 포함된 사운드를 재생할 수 있습니다.

var piano:PianoMusic = new PianoMusic(); 
var sndChannel:SoundChannel = piano.play();

또는 다음에 설명된 대로 [Embed] 메타데이터 태그를 사용하여 Flash Professional 프로젝트에 에셋을 포함할 수 있습니다. 코드에서 [Embed] 메타데이터 태그가 사용된 경우 Flash Professional에서는 Flash Professional 컴파일러 대신 Flex 컴파일러를 사용하여 프로젝트를 컴파일합니다.

Flex 컴파일러를 사용하여 포함된 에셋 클래스 사용

Flex 컴파일러를 사용하여 코드를 컴파일할 경우 ActionScript 코드에 에셋을 포함하려면 [Embed] 메타데이터 태그를 사용합니다. 기본 소스 폴더나 프로젝트의 빌드 경로에 있는 다른 폴더에 에셋을 배치합니다. Flex 컴파일러가 Embed 메타데이터 태그를 발견하면 포함된 에셋 클래스가 만들어집니다. [Embed] 메타데이터 태그 바로 뒤에 선언하는 Class 데이터 유형의 변수를 통해 클래스에 액세스할 수 있습니다. 예를 들어 다음 코드는 sound1.mp3라는 사운드를 포함하고 soundCls 변수를 사용하여 해당 사운드와 연관된 포함 에셋 클래스에 대한 참조를 저장합니다. 그런 다음 이 예제에서는 포함된 에셋 클래스의 인스턴스를 만들고 해당 인스턴스에서 play() 메서드를 호출합니다.

package 
{ 
    import flash.display.Sprite; 
    import flash.media.SoundChannel; 
    import mx.core.SoundAsset; 
 
    public class SoundAssetExample extends Sprite 
    { 
        [Embed(source="sound1.mp3")] 
        public var soundCls:Class; 
         
        public function SoundAssetExample() 
        { 
            var mySound:SoundAsset = new soundCls() as SoundAsset; 
            var sndChannel:SoundChannel = mySound.play(); 
        } 
    } 
}

Adobe Flash Builder

Flash Builder ActionScript 프로젝트에 [Embed] 메타데이터 태그를 사용하려면 Flex 프레임워크에서 필요한 모든 클래스를 가져와야 합니다. 예를 들어 사운드를 포함하려면 mx.core.SoundAsset 클래스를 가져옵니다. Flex 프레임워크를 사용하려면 ActionScript 빌드 경로에 framework.swc 파일을 포함합니다. 이렇게 하면 SWF 파일의 크기가 증가합니다.

Adobe Flex

또는 Flex에서 MXML 태그 정의에 @Embed() 지시문을 사용하여 에셋을 포함할 수 있습니다.