我正在尝试实现类/子类对象的层次结构,例如:
|-- Class1 # mainClass
| |-- SubClassA # subClass
| `-- SubClassB # subClass
`-- Class2 # mainClass
|-- SubClassA # subClass
`-- SubClassB # subClass
这里的要点是能够在每个主要类中声明不同的子类同名(并使其变量独立)。
(注意:我在这里谈论的是在执行期间创建的类<strong>对象的层次结构,而不是关于不同类的遗产。)
对Tcl(命名空间,范围......)特有的一些高级方面相当不熟悉,我尝试了以下代码:
package require Itcl
itcl::class subClass {
variable InternalVariable
constructor {} {
puts "($this) Current namespace : [namespace current]"
puts "($this) InternalVariable scope : [itcl::scope InternalVariable]"
}
}
itcl::class mainClass {
variable SubClassesList
constructor {} {
set SubClassesList {}
puts "($this) current namespace : [namespace current]"
puts "($this) SubClassesList scope : [itcl::scope SubClassesList]"
}
method newSubClass {argName} {
lappend SubClassesList [subClass $argName]
puts "($this) SubClassesList : {$SubClassesList}"
}
}
# Create the two main classes
mainClass Class1
mainClass Class2
# Add some subclasses to Class1 and Class2
Class1 newSubClass SubClassA
Class1 newSubClass SubClassB
Class2 newSubClass SubClassC
Class2 newSubClass SubClassB
在创建SubClassB
的第二次出现时产生错误:
(::Class1) current namespace : ::mainClass
(::Class1) SubClassesList scope : @itcl ::Class1 ::mainClass::SubClassesList
(::Class2) current namespace : ::mainClass
(::Class2) SubClassesList scope : @itcl ::Class2 ::mainClass::SubClassesList
(::mainClass::SubClassA) Current namespace : ::subClass
(::mainClass::SubClassA) InternalVariable scope : @itcl ::mainClass::SubClassA ::subClass::InternalVariable
(::Class1) SubClassesList : {SubClassA}
(::mainClass::SubClassB) Current namespace : ::subClass
(::mainClass::SubClassB) InternalVariable scope : @itcl ::mainClass::SubClassB ::subClass::InternalVariable
(::Class1) SubClassesList : {SubClassA SubClassB}
(::mainClass::SubClassC) Current namespace : ::subClass
(::mainClass::SubClassC) InternalVariable scope : @itcl ::mainClass::SubClassC ::subClass::InternalVariable
(::Class2) SubClassesList : {SubClassC}
command "SubClassB" already exists in namespace "::mainClass"
我可能错过了关于类命名空间的观点,因为我不明白变量SubClassesList
如何具有两个不同的范围,但是“相同”的命名空间/名称(来自调试输出)。
我尝试在newSubClass
方法中创建一个新的命名空间,但它没有解决问题和/或添加一些不可分割的变量命名空间错误......
method newSubClass {argName} {
set SubClassName "[namespace current]::[namespace tail $this]"
puts "($this) SubClassName : $SubClassName"
namespace eval $SubClassName "lappend SubClassesList [subClass $argName]"
puts "($this) SubClassesList : {$SubClassesList}"
}
有没有想过要做这样的事情?
P-S:我使用[incr Tcl]在我的项目中实现类,以兼容现有环境,但如果有人认为其他OO实现会更好/更容易,请告诉我......
使用namespace eval
+ namespace inscope
在与subClass
对象名称对应的新命名空间中创建mainClass
个对象,找到解决方案:
itcl::class mainClass {
variable SubClassesList
constructor {} {
set SubClassesList {}
puts "($this) current namespace : [namespace current]"
puts "($this) SubClassesList scope : [itcl::scope SubClassesList]"
# Create a new namespace corresponding to class name
namespace eval $this {}
}
method newSubClass {argName} {
# Create the subClass object in the $this namespace
lappend SubClassesList [namespace inscope $this subClass $argName]
puts "($this) SubClassesList : {$SubClassesList}"
}
}
答案 0 :(得分:2)
我认为您在类和对象之间感到困惑:Class是用于创建对象的蓝图或模板。在您的示例中:
mainClass
和subClass
是Class1
,Class2
,SubClassA
,SubClassB
和SubClassC
是对象,类的AKA实例在Itcl中,每个类都有自己的命名空间,例如,类mainClass
拥有一个名为::mainClass
的命名空间 - 您在输出中看到了这个证据:
(::Class1) current namespace : ::mainClass
^^^^^^^^^^
此外,每个对象都有自己的命名空间::::。例如,SubClassB
对象拥有名称空间::mainClass:SubClass
:
(::mainClass::SubClassB) InternalVariable scope : @itcl ::mainClass::SubClassB ::subClass::InternalVariable
^^^^^^^^^^^^^^^^^^^^^^^^
这意味着,你不能拥有两个共享相同名称的对象 - 这就是你得到的错误。如果您仍希望示例工作,请使用#auto
作为对象名称:
method newSubClass {argName} {
lappend SubClassesList [subClass #auto] ;# <=== Use automatic naming
puts "($this) SubClassesList : {$SubClassesList}"
}