OTcl

出典: やる気向上作戦

KnowledgeBase


目次

OTcl文法概説

以下の内容は必ずしも正確ではないかもしれません。悪しからず。 誤りを発見された場合、ちょちょっと直しておいて頂けると大変助かります。

OTclNsMemo


OTclとは

もともとはMITで開発された、Tcl言語のオブジェクト指向拡張。派生品にXOTcl(igza'tikl)がある。 ネットワークシミュレータ ns に採用されているため、否応なく覚えることに。


OTcl文法

基本はTcl。Tclコマンドは全てOTclでも使える。Tclの解説書は多く出版されているので、ここでは説明しない。


クラス定義

Class classname -superclass superclassnames

superclassnamesは、スーパークラス名を列挙したリスト。 例えば、クラスSuperClassからクラスSubClassを派生させる場合、

Class SuperClass
Class SubClass -superclass SuperClass

のように書く。


クラスインスタンスの生成・破壊

インスタンスの生成は、

classname instname

もしくは

set refvar [new classname]

破壊は、

delete instname
delete $refvar


インスタンスメソッドの定義

instprocコマンドを使用。

MyClass instproc methodname {arg1 arg2...} {
  method body
}


インスタンスメソッドの呼び出し

インスタンス メソッド名 引数1 引数2 ... の形式。

上の例だと、

MyClass instance
instance methodname These are args

あるいは、

set instref [new MyClass]
$instref methodname These are args


コンストラクタ・デストラクタ及びインスタンス変数の定義

ctor, dtorは、それぞれ「init」、「destroy」という既定の名前を持つメソッド。

MyClass instproc init {args} {
  $self set [fieldname] [initialval] ;# インスタンス変数の定義と初期化
  eval $self next $args              ;# スーパークラスのコンストラクタ呼び出し
}

親のコンストラクタは自動的には呼ばれないため、以下の形式で明示的に呼び出すこと。

eval $self next $args ;#引数のある場合
eval $self next       ;#引数のない場合

たとえ最上位のクラス(-superclassをなにも指定しない)でも、上記呼び出しを行う必要がある。

デストラクタも同様。

MyClass instproc destroy {} {
  body...
  eval $self next ;# スーパークラスのデストラクタ呼び出し
}

たとえ最上位のクラス(-superclassを何も指定しない)でも、デストラクタで親を呼ばなければならない。呼ばなければオブジェクトが破棄されず残るので注意。

親のコンストラクタ/デストラクタが実行されるタイミングは、eval $self nextのメソッド内位置に依存する。


メソッドのオーバーロード

基本クラスのメソッドと同名のメソッドを派生クラスで再定義することができる。 基本クラスのメソッドを呼び出すには、派生クラスメソッド内で以下のように記述する。

eval $self next [args]

メソッドのオーバーライドや、同一クラス内で同名のメソッドを複数定義することは不可能である。


インスタンス変数の参照

メソッド内部から参照するには、コマンド instvar を使用。 instvarはglobalのクラス版と考えればよい。

メソッド内でのインスタンス自身への参照には、特殊変数 $self が使える。

MyClass instproc setField {val} {
  $self instvar m_field
  set m_field $val
  # $self set m_field $val でも同じである。
}
MyClass instproc getField {} {
  $self instvar m_field
  return $m_field
  # return [$self set m_field] でも同じである。
}

クラス外から参照する方が実は簡単だが、一応OOPなのでアクセサを定義するほうがよいだろう。

set instance [new MyClass]
 
$instance set m_field 0               ;# set
set fieldVal [$instance set m_field]  ;# get


クラスメソッドの定義

クラスメソッドの概念は存在しない。

ただし、クラスオブジェクトに直接procを定義することで、類似の効果を得ることができる。


クラス変数の定義

クラス変数の概念は存在しない。

ただし、クラスオブジェクトのインスタンス変数として定義することで、類似の効果を得ることができる。

MyClass set s_classVar 0


クラス変数の参照

直接参照する場合は

set someVar [MyClass set s_classVar]

インスタンスメソッド内から参照する場合は、現在のインスタンスのクラスオブジェクトを保持する特殊変数、$class を用いて以下のように。

MyClass instproc getClassVar {} {
  return [$class set s_classVar]
  # $class instvar s_classVar; return $s_classVar でも同じである。
}

MyClass instproc setClassVar {val} {
  $class set s_classVar $val
  # $class instvar s_classVar; set s_classVar $val でも同じである。
}


リフレクション

オブジェクトのメタデータをinfoメソッドで取得可能。

class info command
instance info command

たとえば

MyClass info instprocs

は、My Classの全てのインスタンスメソッド名をリストで取得

MyClass a
a info vars

は、オブジェクトの持つインスタンス変数を全て列挙

個人用ツール