名字空间

名字空间为命令和变量提供了新的作用域。一个名字空间就是一个变量和命令的集合。名字空间将变量和命令/过程封装起来以避免和其他名字空间的变量和命令冲突。 Tcl 始终有一个默认的名字空间,我们称之为全局名字空间。全局名字空间包含了所有全局变量和命令。 

1. 创建名字空间 

使用 namespace eval 命令可以让你创建新的名字空间。其语法为: 

  • namespace eval spaceName { body } 

定义名字空间 Counter示例:

namespace eval Counter {

  namespace export bump

  variable num 0

  proc bump {} {

    variable num

    return [incr num]

  }

}

上例创建了一个含有变量 num 和过程 bump 的名字空间 Counter。名字空间中的变量和命令与同一程序中的相同名字的变量和命令相隔离。例如在全局名字空间中也有一个 bump 过程的话,它与 Counter 内的 bump 被认为是不同的过程,可以分别使用。 

名字空间的定义是动态的,你可以在需要的时候对名字空间的内容进行更改,也同样是使用namespace eval 命令。如下面的两个命令和上面的名字空间定义命令效果相同(过程 test 首先被添加到名字空间,然后第二次的时候用 rename 将其删除) 

namespace eval Counter {

  variable num 

  proc test{args} {

    return $args

  }

}

 

namespace eval Counter {

  namespace export bump  #两个bump不属于同一个过程

  proc bump {} {

    variable num

    return [incr num]

  }

  rename test ""

}

2. ::限定符来使用变量和过程 

可以使用限定符::来使用名字空间的变量和过程。如:

Counter::test 就可以调用名字空间 Counter 的过程 test,而$Counter::num 引用Counter 中的变量 num。 

对于使用全局变量和过程,可以有两种方法,一种是用 global 声明,另一种是用限定符::引导全局变量和过程,如::num 则引用全局变量 num,用$::num 来获得其值 

直接以::作为前导的名字我们称之为“全限定名”,它指明在全局名字空间中对其进行解析。而没有::作为前导的名字为“部分限定名”,它指明从当前的名字空间中对其进行解析。如:

  •  ::foo::x 

表明 x 属于 foo 为全局名字空间的名字空间,而 

  •  foo::x 

表明 x 属于 foo 为当前名字空间(不一定是全局名字空间)的名字空间。 

namespace eval foo {

  namespace eval foo {

    proc test {} {

      puts "In ::foo::foo::test"

    }

  }  

 

  proc test {} {

    puts "Enter ::foo:test"

    puts "Call ::foo::foo::test"

    foo::test  #调用::foo::foo::test

    puts "End ::foo:test"

  }

  foo::test  #调用::foo::foo::test

  ::foo::test  #调用::foo::test

}  

 => In ::foo::foo::test

  Enter ::foo:test

  Call ::foo::foo::test

  In ::foo::foo::test

  End ::foo:test

3. 名字空间的变量 

名字空间中的变量用 variable 定义,它类似与全局变量,名字空间中的过程要使用variable 命令可以使用名字空间的变量。 

语法:

  • variable name ?value? ?name value ? ?... name value? 

可以用 variable 先声明变量而将赋值操作留到后面。但如果先声明而在不赋值情况下引用变量的话,会出错。 

posted @ 2024-04-18 21:06  小熊酱  阅读(2)  评论(0编辑  收藏  举报