I have next code:
oo::configurable create Temp {
superclass SPICEElement
property name -set {
set name [string tolower $value]
}
property value -get {
return [$value configure -value]
}
variable name value
constructor {value args} {
# Creates object of class `Temp`.
# value - value of the temperature
# args - optional parameter qualificator -eq
# This class represent .temp statement with temperature value.
set arguments [argparse {
{-eq -boolean}
}]
my configure -name temp
if {$eq} {
my AddParam temp $value -eq
} else {
my AddParam temp $value
}
}
method AddParam {paramName value args} {
# Adds temperature parameter.
# paramName - name of temperature parameter
# value - value of temperature
# args - optional parameter qualificator -eq
set arguments [argparse {
{-eq -boolean}
}]
if {$eq} {
set value [::SpiceGenTcl::ParameterPositionalEquation new $paramName $value]
} else {
set value [::SpiceGenTcl::ParameterPositional new $paramName $value]
}
return
}
method genSPICEString {} {
# Creates .temp statement string for SPICE netlist.
# Returns: '.temp $Value'
return ".temp [[my configure -value] genSPICEString]"
}
}
oo::define Temp {
method <WriteProp-value> val {
lassign $val value eq
if {$eq=="-eq"} {
my AddParam temp $val -eq
} elseif {$eq==""} {
my AddParam temp $val
} else {
return -code error "Wrong value '$eq' of qualifier"
}
}
}
Objects ::SpiceGenTcl::ParameterPositionalEquation
and ::SpiceGenTcl::ParameterPositional
have the property with the same name value
.
So,when I try to run next test:
test testTempClass-1 {test creation of Temp class instance and genSPICEString interface} -setup {
set temp [Temp new 10]
} -body {
set result [$temp genSPICEString]
} -result ".temp 10" -cleanup {
unset temp result
}
I got the next error message:
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: can't read "value": no such variable
while executing
"$value configure -value"
(class "::SpiceGenTcl::Temp" method "<ReadProp-value>" line 2)
invoked from within
"my configure -value"
(class "::SpiceGenTcl::Temp" method "genSPICEString" line 4)
invoked from within
"$temp genSPICEString"
("uplevel" body line 2)
As you can see, I redefine the method <WriteProp-value>
to allow use val
name as variable name inside the setter. It works, but doesn't work for custom -get
method, and I don't understand why. It should call object stored in value
property with configure
method of that object, and return the string stored in the value
property of called object. I assume I should redefine the <ReadProp-value>
instead of defining it in property
, but it also failed with the same error.
Thank you in advance.
You need to have set the variable in the object in order to read it in the implementation of the property reader. So far, so simple. The issue is that the constructor isn't writing to the instance variable. The reason why is annoying.
It is because the Tcl procedure compiler (methods reuse it, constructors are special methods) has resolved value
to a formal argument and so doesn't even look at the instructions about that variable set up in the variable
declaration. You need to set the variable by some other mechanism.
Any of these would go in the constructor.
set [my varname value] $value
Relies on the fact that the default varname
method ignores local variables entirely by design. (It's intended for producing global handles for vwait
and Tk widgets, but it works here just as well.)
my configure -value $value
If the property is writable, you can just write it. Local variables won't confuse it. I think this is more elegant, but it does constrain the property to be standard-model-writable.
Or you can just alter the name of the argument to the constructor or the instance variable.