2

Inside a constructor, destructor or method, can I find out what namespace the class was created in, so I can just call card in my other classes instead of hard coding it as blackjack::card?

namespace eval blackjack {

  oo::class create card {
    ...
  }

  oo::class create deck {
    constructor {} {
      my variable cards
      set cards {}
      for {set suit 0} {$suit < 4} {incr suit} {
        for {set value 0} {$value < 13} {incr value} {
          lappend cards [blackjack::card new $suit $value]
        }
      }
    }
    ...
  }

}
4

1 回答 1

3

选项 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(你认为这是从哪里来的?nextself

选项 4:创建命令链接

您还有另一个选择,那就是使用namespace exportnamespace 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 在内部使用这种方法的变体来将语句与连接和结果集与语句相关联。)

于 2013-04-22T09:36:45.430 回答