Flash 개발하면서


지겹도록 쓰는 구문 두개가 바로 다음이 아닐까 합니다.


public class Game
{
     public function Game()
     {
     }
}


var game: Game = new Game();


거의 1+1 수준으로 외워서 쓰고 자주 쓰다보니 그 의미를 이해할 기회가 없었습니다.


하지만 이런 생각 해보신 적 없나요?


왜 초기화 함수에는 리턴 타입을 선언해주지 않는거지?


public function Game()


이라고만 쓰지 


public function Game(): Game


이런식으로 쓰지 않습니다.


왜 일까요?


그 이유는 Virtual Machine이 해주는 일을 숨겨주기 위한 것입니다.


결론부터 간단하게 이야기하자면


이 초기화 함수의 숨겨진 부분은


다음과 같습니다.


public class Game
{
     public function Game()
     {
          // do something
          
          return this;
     }
}


바로 return this 부분이 VM이 몰래 해주는 일입니다.


예를 들기 위해서 알아보기 쉬운 코드로 적은 것입니다. 실제로 저렇게 돌아가진 않아요 ㅋㅋ




그럼 더 깊게 들어가볼까요?


깊게 들어가기 위해서는 다음 구문을 주의 깊게 봐야합니다.


var game: Game = new Game();


자 여기서 실제로 VM이 하는 일은 크게 3가지로 나눌 수 있습니다.


1. 메모리 할당

var game: Game = new Game();


2. 초기화 함수 실행

var game: Game = new Game();


3. 좌항 대입

var game: Game = new Game();


하나씩 살펴보죠.




1. 메모리 할당


new 라는 키워드는 예약어죠.


유저가 변수나 클래스명으로 쓸 수 없다는 것이죠.


이 new 라는 명령어가 하는 역할은


뒤에 오는 클래스를 가져다가


이 클래스의 인스턴스를 만들기 위한 메모리를 할당합니다.


만약 


public class Game
{
     public var name: String = "merong";
     public var id: int;

     public function Game()
     {
          id = 12;
     }
}

이런 클래스가 있다고 하면


new Game 이라고 하면


Game이라는 클래스를 보고


"아 이 클래스는 name이라는 String 변수가 있으니 이곳(메모리주소)에다 값을 적을 준비를 해야겠다.


그리고 id 라는 int 변수가 있으니 이곳(메모리주소)에다가 4바이트(32비트) 공간을 자리 잡아놔야지"


라고 하는 것입니다.


즉, 클래스의 구조를 보고 그대~로 메모리를 비워놓는거죠.




2. 초기화 함수 실행


초기화 함수에서는 이렇게 자리 잡아놓은 메모리에


값을 넣는 역할을 합니다.


위에서


public var name: String = "merong";


이라고 써있는 부분은 마치 초기화하지 않아도 기본으로 값이 들어가 있을 것이라고 생각할 수 있지만


컴파일을 하는 순간에 다음과 같이 코드가 inline 화 됩니다.


public class Game
{
     public var name: String;
     public var id: int;

     public function Game()
     {
          name = "merong";
          id = 12;
     }
}

초기화 함수가 하는 일로 치환된다는 것이죠.


즉 new Class() 에서 () 이 괄호가 하는 일은


초기화 함수를 그저 "실행"만 시켜주는 역할을 합니다.


Q) Flash에서는 new Game; 이라고만 해줘도 된다는데요?


A) Flash는 기본적으로 클래스명과 동일한 함수를 초기화 함수로 인식합니다.


반대로 유추하면 내부에서는 초기화 함수를 내 마음대로 지정할 수도 있다는 뜻입니다. (클래스명은 Game인데 초기화 함수는 createGame 메소드로 한다던가)


하지만 이렇게 되면 VM이 처리해야하는 일이 너무 많아지고


개발자도 소스 분석이 어렵게 되는등 패널티가 많아집니다.


이 약속하나로 얻어지는 이득이 매우 많기 때문에


클래스명과 동일한 메소드명을 초기화 함수로 하자는 "약속"인 것입니다.


이렇게 값이 대입되고 


인스턴스로 쓰일 준비가 되면


마지막에 함수 끝에서 return this 라고 숨겨진 코드가 실행하게 되면서 자기 자신을 넘기게 되죠.




3. 좌항 대입


이렇게 초기화 함수에서 넘어온 객체를


좌항에 대입하게 되는 것입니다.


다들 아시겠지만


리턴 값이 void 인 메소드는 대입하는 구문에 쓰면 에러가 나죠.


function setName( $name: String ): void
{
     _name = $name;
}

// 에러
var currentName: String = setName( "merong" );


하지만 객체를 반환하는 메소드일 경우에는 정상적으로 동작합니다.


function setName( $name: String ): String
{
     _name = $name;

     return _name;
}

// OK
var currentName: String = setName( "merong" );


이해가시죠?


왜 초기화 함수에는 리턴 타입이 없는지?


자기 자신을 반환하기 때문입니다.


엄밀하게 따지면 메모리 주소 즉, 포인터를 넘기기 때문입니다.







var game: Game = new Game();


이 간단한 구문에 이렇게 복잡한게 숨어있었을줄 저도 몰랐습니다.


이제 여러분이 짜는 코드에 조금 더 새로운 눈으로 코딩을 하실지도 모르겠습니다.






For the better.

+ Recent posts