'create a class object as variable in Tcloo

I start to use tclOO. I need to create a Aclass instance anotherClassIns in my main class MainClass as below:

oo:class create Aclass {
    variable num;
    constructor {argv} {
       set num [lindex $argv 0]
    }
}; #end of Aclass


oo:class create MainClass {
    variable anotherClassIns ; # this variable is another class's instance!
     
    constructor {argv} {
       Aclass create anotherClassIns {$argv};
    } 
} 

And in main function, I create a MainClass instance:

MainClass create Ins $argv

If I want to print $num in Aclass, how can I do?

Thanks.



Solution 1:[1]

All instance variables in TclOO have globally-addressable names so that they can be used with other parts of Tcl that expect such (especially vwait and trace, but also Tk's -textvariable options).

The easiest way for now is to make an accessor method:

oo:class create Aclass {
    variable num
    constructor {argv} {
        set num [lindex $argv 0]
    }
    method num {} {
        return $num
    }
}
oo:class create MainClass {
    variable anotherClassIns
     
    constructor {argv} {
        set anotherClassIns [Aclass new {*}$argv]
    }
    destructor {} {
        # Assuming you're owning the inner instance
        $anotherClassIns destroy
    }

    method printTheValue {} {
        puts [$anotherClassIns num]
    }
} 

You can also access the variable directly by using the fact that variables exist in a namespace, and that namespace can be looked up with info object namespace:

    method printTheValue {} {
        # Probably easiest to do this
        namespace upvar [info object namespace $anotherClassIns] num v
        puts $v
    }

But that won't work with 8.7's private variables, as those are name-mangled in a way that is decidedly non-accessible to outside code. In that case, you'd need to get Aclass to provide access into its internals; that's literally the point of private variables. The varname method of oo::object can help there; it's not exposed by default, but it's available internally via my, and you can expose it for a class or even just an instance via the export definition.

# Probably at object creation time
oo::objdefine $anotherClassIns export varname

# Then, to access
puts [set [$anotherClassIns varname num]]
# Or
upvar 0 [$anotherClassIns varname num] v
puts $v

There's a similar variable method, but that requires that you don't have a colliding local num variable:

# Object creation time
oo::objdefine $anotherClassIns export variable

# Access
$anotherClassIns variable num
puts $num

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Donal Fellows