2006-1-16开始有了时间学习Tcl,在熟悉了这门语言的基本语法后,很快就转向了它的面向对象的扩展Incr Tcl。
ITCL模拟了C++的面向对象特征,支持单继承和多继承(多态,目前还没有发现有关这方面的资料)。
首先从TCL背景知识入手介绍一个很重要的概念,其实这个概念从语言名称就已经体现了:TOOL Command Language,工具命令语言,它是一种脚本,就象VBA语言提供的把各种对象粘合在一起功能,在内存管理方面,脚本中的所有变量在统一名字空间中必须唯一(从Tcl引入名字空间这个概念推断,Tcl把变量保存到为平板型的名值对中,通过变量名称查找变量值)由于这个要求,使在使用这个语言的面向对象特征的过程中,遇到了麻烦。
本文只是记录解决问题的一个过程:
问题是:
首先编写两个itcl类:
package require Itcl
namespace import itcl::*
class Person {
variable m_name
variable m_sex
variable m_age
#constructor {} {
#}
constructor {name sex age} {
set m_name name
set m_sex sex
set m_age age
puts "create person $this"
}
destructor {
puts "destroy object $this"
}
}
class Family {
variable m_father
variable m_mother
variable m_sister
variable m_brothor
constructor {father mother} {
set m_father father
set m_mother mothor
set m_sister [Person m_sister "mary" "female" 22]
set m_brother [Person m_brother "john" "male" 19]
}
}
首先,声明了一个类Person,然后在Family类中使用这个类:
在Family类中实例化一个Person对象并赋值给m_sister。
现在就可以打开一个tkcon控制台,把以上代码复制进来后,接下来的操作出了问题:
实例化第一个Family对象,成功,而声明第二个的时候,问题如下:
按照面向对象思想,Family类中的变量都是实例变量(而不是静态变量),一个类的多个实例就拥有多个实例变量,而目前这个错误显示,Itcl不能够很好的实现这个问题。
command "m_sister" already exists in namespace "::Family"
实际上,针对这个问题,Itcl提供了一个办法,那就是使用#auto机制。示例如下:
set m_brother [Person #auto "john" "male" 19]
#auto可以生成随机的实例名字,保证不会重复,然后把这个变量使用命令置换,置换给变量m_brother.
重写上面的Family类如下:
class Family {
variable m_father
variable m_mother
variable m_sister
variable m_brothor
constructor {father mother} {
set m_father father
set m_mother mothor
set m_sister [Person #auto "mary" "female" 22]
set m_brother [Person #auto "john" "male" 19]
}
}
修改这个类:
delete class Family
复制上面的代码进入tkcon后,创建几个该类的实例如下:
问题得到了解决。
删除对象的方法:
delete object h3
我们在项目中还用到了Tcl中的图:
::struct::graph是一个结构,它被应用在类中,在类被进行第二个实例化时也碰到了这个问题。由于#auto机制不适用于结构,所以自己写了一个静态类,借此机会描述一下Itcl的静态类。
这个有一个静态成员和一个静态函数,该函数提供一个唯一名字。
class CAuto {
public common count 0
proc getName {} {
incr count
return [concat "obj" $count]
}
}
其中的common声明静态变量,proc用在类中表示声明静态成员函数。
使用如下:
set m_lnkseg [::struct::graph CTool::GetName]
如此也解决了问题。
以上解决办法,从根本上说是由于tcl的变量名称可以是单词符号,也可以是变量的变量,即解释执行的脚本语言。这种情况放在象C++、Java等语言中是无法走通的。