首页 > 解决方案 > TclOO : 从另一个类获取基础对象

问题描述

我有 2 个类fruitorange我的目标是获得允许我构建类的对象fruit

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"]

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

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
    }
}

有什么命令,另一种解决方案吗?我不知道我的方式是否是面向对象的......

标签: tcl

解决方案


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

尤其:

  • info class instances Foo获取类的实例Foo
  • info class subclasses Foo获取类的(直接)子类Foo
  • info class superclasses Foo获取 class 的(直接)超类Foo::oo::object如果您没有另外说,这将是;所有类都将其作为最终的超类。
  • info object class bar获取对象的类bar
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

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

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


如果你想安排一个对象被另一个对象拥有,即在所有者对象被销毁时自动销毁,最简单的方法是让拥有对象的名称在所有者的实例命名空间中(create方法oo::object在解析你给它的名字的意思时是命名空间感知的),然后它会在所有者离开时自动销毁,不需要显式销毁。

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

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

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

请注意,该new方法oo::object使名称不是以这种方式拥有的。(或者更确切地说,它生成的名称归 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]]
    }
}

推荐阅读