본문으로 바로가기

Tcl의 오브젝트 지향 Snit

category 카테고리 없음 2024. 6. 25. 11:28

http://www.wjduquette.com/snit/

 

Snit은 Snit’s Not Incr Tcl의 준말입니다. (GNU가 GNU’S Not UNIX 인 것처럼 말이죠.) Snit은 incr Tcl과는 다른 오브젝트 체제입니다. Snit에 의하여 정의된 오브젝트 타입은 서브 커맨드를 갖는 Tcl 커맨드처럼 보입니다. 다소 복잡한 incr Tcl과 비교하여 심플하면서 쉽게 익힐 수 있습니다. Snit의 특징입니다.

  • 100% 순수 Tcl로 작성되어졌습니다.
  • 클래스와 같은 상속을 지원하지 않습니다.
  • 클래스 대신 오브젝트 타입을 사용합니다.
  • 오브젝트 타입은 namespcae로 정의됩니다.
  • 오브젝트 타입에는 변수나 메쏘드 및 옵션을 정의할수 있습니다.
  • 다른 오브젝트의 메쏘드및 옵션을 상속할 수 있습니다.
  • Tk 위젯을 사용하여 MegaWidget을 작성할 수 있습니다.
  • Tcl8.4 이상이 필요합니다.

타입과 인스탄스

아래의 코드는 Hello라는 이름의 타입에 변수 var와 메쏘드 print가 정의되었습니다. 변수 var와 메쏘드 print는 global 영역이지만 다른 타입으로 정의된 것과는 충돌하지 않습니다.

아래와 같이 인스탄스를 생성합니다.

아래의 방법으로 인스탄스 혹은 타입을 삭제합니다.

변수와 메쏘드

타입의 변수는 그 변수를 참조하는 메쏘드외에 액세스 할 수 없습니다. 하지만 아래와 같이 namespcae를 사용하여 강제적으로 액세스는 가능합니다.

 

 메쏘드는 서브 커맨드와 같은 방법으로 액세스 합니다.

private 메쏘드

메쏘드 정의 시 보통 public 권한을 갖습니다. private 권한을 주고 싶으면 proc를 사용합니다.

private 권한을 갖는 메쏘드를 강제적으로 액세스시 다음과 같이 합니다.

 

메쏘드에서 메쏘드를 호출 시, 호출한 메쏘드의 첫 번째 인자에 namespcae 이름을 줘야 하며, 위의 경우 selfns 변수는 namespcae의 이름이 됩니다. $selfns의 내용은

::Hello::Snit_inst1

이 됩니다.

static 멤버와 static 메쏘드

static 메쏘드는 타입의 인스탄스로 부터 액세스 할수 없습니다. static 멤버를 정의시 typevariable을 사용합니다. static 멤버는 모든 인스탄스에서 공유됩니다. static 메쏘드를 정의시 typemethod를 사용하며, 메쏘드의 호출에는 인스탄스 이름이 필요치 않습니다. static 메쏘드는 타입의 서브 커맨드로써 호출합니다.

 type 변수는 타입의 이름이 되며, 이 경우 $type의 내용은

::Count

 

 가 됩니다.

생성자와 소멸자

생성자는 인스탄스 생성시에, 소멸자는 인스탄스 제거 시에 호출되는 특수한 메쏘드입니다. 기본 생성자는 인자를 갖지 않지만 옵션 처리를 위해서 args를 받습니다.

 

인자를 갖는 생성자도 정의할 수 있습니다.

옵션

Snit의 타입에는 옵션의 개념이 있습니다. 아래의 예는 -lang 옵션을 받아 메시지를 리턴합니다.

 

options 배열 변수는 옵션의 상태를 기억하고 있는 멤버입니다. onconfigure는 옵션의 설정 시에 호출되며, 여기서는 옵션의 상태를 기억시킵니다. oncget의 옵션은 참조 시에 호출되는 옵션을 정의할 때 사용됩니다. 모두 (on*) 생략 가능합니다.

영역

Tcl은 이벤트를 사용하여 커맨드를 실행할 수 있습니다. after 커맨드, bind 커맨드, button -command 커맨드 등이 이에 해당됩니다. 이벤트는 global 영역에서 실행된다는 점에 주의하여야 합니다. 예를 들어 아래의 예는 after로 1초 후에 커맨드가 실행되지만, 커맨드가 실행된 것은 global 영역이므로 변수 var가 정의되지 않다는 에러를 냅니다.

 

해결방법은 codename 커맨드로 namespcae를 사전에 해결한 코드로 생성하는 방법입니다.

 

사전에 해결한 코드($cmd 변수의 내용)는 아래처럼 되며, codename 커맨드는 지정된 namespace로 인자의 커맨드를 실행합니다

::Hello::doprint 
::Hello::Snit_inst1

 

만약 위의 doputs 메쏘드가 public 메쏘드일 경우 아래와 같이 기술합니다.

 

사전에 해결한 코드는 아래처럼 되며, self 변수는 지정된 namespace로 인자의 커맨드를 실행합니다. 

::foo doputs

MegaWidget

Snit를 사용하면, Tk의 위젯을 사용하여, 새로운 MegaWidget을 작성할 수 있습니다. MegaWidget을 작성 시 ::snit::type 대신 ::snit::widgetadaptor를 사용합니다. 아래의 예는 Tk의 checkbutton에 ison 커맨드와 -ison 옵션을 추가합니다.

 

누른 상태를 유지하는 pushbutton입니다. 버튼의 상태는 ison 커맨드 혹은 -ison 옵션으로 확인할 수 있습니다.

마치며

Snit은 클래스의 파생 개념 대신 메쏘드 및 옵션의 상속받는 것을 가능케 하는 특별한 방법을 사용합니다. 결과적으로는 클래스의 파생과 동일한 효과를 얻을 수 있습니다. 이전의 오브젝트 지향 프로그래밍과 비교하여 상당히 심플합니다.