뭔가 좌절스럽다. 아무리 현재 구현인 Flash 9 / ActionScript 3.0이 아니라지만 (Flash 8/ActionScript 2.0임) 이렇게 쓰기 괴로운 스크립트 언어는 처음이다. Python 을 처음 접했을 때 느꼈던 편안한 프로그래밍 같은 거랑은 수억 광년 떨어진 무언가인 느낌
Class 는 무조건 별도의 파일로
.fla 에서 class 키워드를 썼더니 — 밑에서 언급하는 문제를 검사하려고 — class는 외부에 선언해라! 라는 오류 메시지만…
Class 는 하나의 파일에 1개만
x.as 에는 class x만 선언할 수 있다. (이름이 맞지 않으면 그것도 오류) 그리고 x.as에 class a를 선언하면 안된다는 오류를 볼 수 있다.
Sibling member function을 함수 포인터를 통해 호출할 때 비정상 동작
이거 덕분에 2시간 날렸다. 책임져라 Adobe. -_-
this pointer(?)의 scope는 함수 포인터를 통해 멤버 함수가 호출된 순간(…)까지만 유지된다. 예를 들어서
class A { private var n:Number = 1 private var f:Array = [ f0, f1, f2 ] public function f0():Boolean { return true } public function f1():Boolean { return this.n == 1 } public function f2():Boolean { return f1() } public function f3():Boolean { return this.f[0]() } public function f4():Boolean { return this.f[1]() } public function f5():Boolean { return this.f[2]() } }
가 있다고 치자. A의 instance를 만들고 f0~f5 까지 호출하면 어떤 결과가 나올까? 프로그래밍언어에 조금이라도 익숙하다면 모두 같은 결과(true)가 나올 거라고 생각할 것이다…
그러나 ActionScript 는 기대를 저버리지 않고(…) 다음과 같은 결과를 내놓는다.
truetruetruetruefalseundefined
…처음 4개는 결과가 제대로(혹은 예상대로?) 나왔다. 그렇지만 f4를 호출했을 때 this 포인터가 함수 안까지 전달이 되지 않아서? 해석이 되지 않아서? 여튼 this 포인터를 f1/f2이 제대로 받아들일 수 없는 형태로 함수가 호출되고, false, undefined라는 정말 색다른(…)결론을 내려준다. f3의 결과가 제대로 나온 것은 아마 f0가 this를 참조하지 않아서라고밖엔;
이런 형태의 코드를 짜고 있었는데 this가 참조되지 않을꺼라곤 상상도 못했는데, 여튼 그런결과를 내서 저런 류의 함수에 첫번째 인자로 this 에 해당하는 값이 언제나 전달되게 수정했다. ((일종의 on–the–fly로 만들어내는 다형성이 필요했는데 덕분에 아주 제대로 삽질한듯함))
참으로 흠좀무한 언어군요.
혹시 이렇게 명시적으로 this를 주면 어떻게 되나요?
private var f:Array = [ this.f0, this.f1, this.f2 ]
그렇게 선언한 경우 밑의 세개가 모두 undefined.
생성자에서 저렇게 써준 경우엔 위랑 똑같은 결과가 나옵니다(…)
하하 ^^; this.f[1].call(this); 라고 해주면 될 것 같네요.
AS2 문서의 Function 클래스 설명을 보시면 나오죠. 이것도 AS1 legacy문제;;
저도 애매한 function scope때문에 고생 좀 했었다는.
…
non-compatible mode 켜는 것 같은건 없냐 -_-;;
진짜 이건 절망이다 Orz
다만 오늘 부로 모든 변할 수 있는 코드를 C++/Python 의 영역으로 옮겨서 아마도 당분간은 ActionScript를 더 안볼듯하긴하다 ㅠㅠ
JavaScript의 객체 모델을 이해하시면 왜 저런 현상이 일어나는지 알 수 있습니다. 저확히 말하자면, this는 메서드가 어떻게 호출되냐에 따라 다르게 결정됩니다. 예를 들어,
function test() { return this.value; }
var a = { value: ‘a’, test: test };
var b = { value: ‘b’, test: test };
위와 같이 있을 때, a.test()는 ‘a’를, b.test()는 ‘b’를 반환합니다. 그렇다면 그냥 test()를 호출하면 어떻게 될까요? JavaScript에서는 모든 문맥이 객체로 되어 있습니다. 따라서 undefined가 나오게 됩니다. 다만 저 상태에서
var value = 123;
으로 정의해두고 test()를 호출하면 123이 반환됩니다. 결국 문맥 객체라는 것은, 리시버 없는 일반 식별자 접근(예를 들면 test)에 대해 암시적인 리시버가 되는 객체를 뜻합니다(contextObject.test).
AS가 웹에 기반을 둔 언어이기도하고 ECMA 객체 모델을 따라간것은 좋은데, (그쪽에 기반을 두지 않은) rein같은 프로그래머에겐 너무 생소한게 많군요 Orz