我正在调查TclOO
,发现我们可以使用create
或new
来创建对象。
使用create
我们可以提供自定义名称,而使用new
时,它是由计算机生成的。
#!/bin/bash
#\
exec tclsh8.6 $0 $@
::oo::class create calc {
method add { a b } {
return [ expr {$a+$b} ]
}
}
calc create c;
set t [ calc new ]
# Both serves the same purpose here
puts [ c add 3 4 ]
puts [ $t add 1 2 ]
只是编译器为开发人员提供的对象命名方便吗?另外,我应该选择new
而不是create
的情况呢?
答案 0 :(得分:4)
new
和create
之间的唯一区别是完全,create
允许您提供要使用的名称,而new
会让您重新认识一个给你。某些类型的对象(特别是类)隐藏了它们的new
方法,因此强烈建议你只创建命名实例 - 考虑到人们如何使用类,这在实践中很有意义 - 但它只是隐藏而你可以如果你想要覆盖:
oo::define oo::class {
export new
}
当您不关心名称时使用new
,只是希望它与其他所有名称不同。这是基本的经验法则。
使用create
创建其他OO系统可能使用单例的实例也是完美的。比给他们一个你控制的好名字更独特的是。
我知道的主要场景,否则使用create
更有用的是当你想要将对象的生命周期限制到另一个对象时。在这种情况下,在另一个上下文中创建对象会将对象句柄放在容器的命名空间中,并在删除容器时自动触发删除:
oo::class create InsideThing {
constructor {} {
puts "Made a [self] that is an InsideThing"
}
destructor {
puts "Deleted a [self] that is an InsideThing"
}
}
oo::class create Container {
constructor {} {
puts "Created a [self] that is a Container"
InsideThing create inner1
InsideThing create inner2
}
destructor {
puts "Deleted a [self] that is a Container"
}
}
set c [Container new]
puts "Do stuff..."
$c destroy
如果你运行该代码,你会得到这个:
Created a ::oo::Obj13 that is a Container Made a ::oo::Obj13::inner1 that is an InsideThing Made a ::oo::Obj13::inner2 that is an InsideThing Do stuff... Deleted a ::oo::Obj13 that is a Container Deleted a ::oo::Obj13::inner1 that is an InsideThing Deleted a ::oo::Obj13::inner2 that is an InsideThing
这种技术在TDBC中被广泛用于管理容器上下文中的结果集和语句(分别是语句和连接)。
最后,如果你使用TclOO创建Tk megawidgets,你将肯定使用create
但是被覆盖的形式,因为Tk小部件必须具有不合格的名称以.
开头,具有特定的具体层次结构,并强烈建议非常遵循相同的模式。因为在这种情况下名称很重要,new
是错误的方法;最好从create
开始。 Tk 8.6有一些支持类(没有公开描述,但在内部用于某些对话框),这使得这类事情变得更容易:tk::Megawidget
和tk::MegawidgetClass
。有关详细信息,请查看Tk 8.6发行版中的megawidget.tcl
。