TclOO:从另一个 class 获取基础对象

TclOO : Get base object from another class

我有 2 classes fruitorange,我的目标是获得 object 让我可以构建我的 fruit class.

namespace eval test {}

oo::class create test::fruit {

    constructor {type} {
        if {$type eq "orange"} {
            set orange [test::orange new]
        }
    }
    
    destructor {
        puts "[self] destroy..."
    }
}

oo::class create test::orange {

    constructor {} {
    }
    
    destructor {
        puts "[self] destroy..."
    }
}

set f [test::fruit new "orange"]

我通过将 orange 变量保存在全局变量 baseobject 中找到了找到基础对象 (from class ::test::fruit) 的解决方案,如下所示:

oo::class create test::fruit {

    variable baseobject

    constructor {type} {
        if {$type eq "orange"} {
            set orange [test::orange new]
            set baseobject $orange
            
        }
    }

    method baseclass {} {
        return $baseobject
    }
}

是否有任何命令,另一种解决方案?不知道我的方法是不是面向对象...

我不能 100% 确定您要在这里做什么。您可以使用 info objectinfo class 来获取 TclOO 系统知道的所有关系;他们从为整个系统提供动力的底层 C 结构中读取信息。

特别是:

  • info class instances Foo 获取 class Foo.
  • 的实例
  • info class subclasses Foo 获取 class Foo.
  • 的(直接)子 classes
  • info class superclasses Foo 获得 class Foo 的(直接)超级classes。如果您没有另外说明,这将是 ::oo::object所有 classes 都将其作为终极超级class。
  • info object class bar获取对象bar的class。
oo::class create Foo
oo::class create Foo2 {superclass Foo}
Foo create bar

puts [info class instances Foo];    # => ::bar
puts [info class subclasses Foo];   # => ::Foo2
puts [info class superclasses Foo]; # => ::oo::object
puts [info object class bar];       # => ::Foo

如果对象与 classes 之间的关系不是标准关系之一,则您必须自己捕获;有几种方法,您已经知道其中一种简单的方法,即以某种方式将名称保存在实例变量中。

还要记住,所有 classes 本身都是其元 class 的实例,称为 oo::class(或其子 classes 之一)。这意味着您可以使用 info object class Foo 来获取创建 Foo 的 class。是的,这意味着 oo::class 是它自己的一个实例;它的构造(以及 oo::object 的构造)是 special.


如果你想安排一个对象被另一个对象拥有,即当所有者对象被销毁时自动销毁,最简单的方法是使所拥有对象的名称在所有者的实例命名空间中(oo::objectcreate 方法在解析你给它的名称的意思时是命名空间感知的),然后它会在所有者走了,不需要明确销毁。

method makeMyOrange args {
    test::orange create myOrange {*}$args
}

如果您只有一组固定的拥有对象,那么在您的实例命名空间中为它们指定您喜欢的名称是微不足道的。否则,用于生成名称的简单实例本地计数器也是微不足道的:

method makeOneOfMyOranges args {
    variable counter
    test::orange create myOrange[incr counter] {*}$args
}

请注意,oo::objectnew 方法生成的名称并非以这种方式拥有。 (或者更确切地说,它创建的名称属于 TclOO 本身。)


如果你想让其他随机对象知道是谁创建的,将 [self] 作为参数传递给构造函数。

oo::class create test::orange {
    constructor {maker} {
        puts "I was made by $maker"
    }
}

oo::class create test::fruit {
    constructor {} {
        set orange [test::orange new [self]]
    }
}