选项 0:完全限定名称
您已经知道这一点,而且我实际上几乎总是这样做,因为它直接而简单。(这是“选项 0”,因为它没有提出问题。)
选项1:uplevel
你可以这样做:
lappend cards [uplevel 1 [list card new $suit $value]]
但这取决于deck new
从正确的命名空间调用。
选项 2:类名手术
如果我们假设这两个类在同一个命名空间中:
constructor {} {
set cardClass [namespace qualifiers [self class]]::card
# ...
lappend cards [$cardClass new $suit $value]
# ...
}
选项 3:扩展对象的namespace path
如果您添加到对象的路径(注意:现在必须在构造函数中基于每个对象完成),那么您可以简单地引用另一个类:
constructor {} {
namespace path [list {*}[namespace path] ::blackjack]
# ...
lappend cards [card new $suit $value]
# ...
}
这里要注意的主要事情是 TclOO 设置了一个重要的默认值namespace path
(你认为这是从哪里来的?next
)self
选项 4:创建命令链接
您还有另一个选择,那就是使用namespace export
并namespace import
创建一个命令链接。
首先,从命名空间中导出相关类::blackjack
:
namespace eval ::blackjack {
namespace export card; # You probably want to export “deck” as well
# ...
}
然后,在构造函数中进行导入:
constructor {} {
namespace import ::blackjack::card
# ...
lappend cards [card new $suit $value]
# ...
}
deck
选项 5:在实例中创建一个特殊的子类
这个很棘手!
constructor {} {
oo::class create card {superclass ::blackjack::card}
# ...
lappend cards [card new $suit $value]
# ...
}
这也意味着当牌组消失时,卡片将被自动删除;您不需要在析构函数中销毁它们(因为它们的实际类将被自动删除,并且会杀死实例)。这可能是也可能不是你需要的。(它确实提供了一种对 UML 组合关系进行建模的好方法;TDBC 在内部使用这种方法的变体来将语句与连接和结果集与语句相关联。)