I'm trying to implement classes implementing interfaces and serialisation of the resulting objects and I encountered an objdefine error message (using Tcl 8.5 + TclOO 1.0.x).
I think I have some notion of the cause, but I'm not sure of a workaround other than recompiling TclOO and patching.
I've made a minimal example:
package require Tcl 8.5
package require TclOO
# https://wiki.tcl-lang.org/page/Serializing+TclOO+objects#mkup_code_2
::oo::class create ::oo::serializable {}
# https://wiki.tcl-lang.org/page/Extending+TclOO+with+metaclasses#mkup_code_10
::oo::class create ::oo::interface {
superclass ::oo::class
mixin ::oo::InterfaceMixin
self method create {name args} {
set instance [next $name {*}$args]
# this line appears to cause the problem
::oo::define $instance superclass -append [self]
return $instance
}
}
namespace eval ::csh::oo {}
# creates instances with createWithNamespace
::oo::class create ::csh::oo::nclass {
superclass ::oo::class
mixin ::oo::InterfaceMixin
...
}
::oo::interface create ::SpecialMethods {
}
::csh::oo::nclass create ::ABC {
superclass ::oo::serializable ::SpecialMethods
}
set abc [::oo::serializable new]
# error in Tcl 8.5 + TclOO 1.0.x
# ok in Tcl 8.6.12
::oo::objdefine $abc class ::ABC
# error: "may not change a non-class object into a class object"
can the ::oo::interface class be changed to make ::oo::objdefine work?
running under GDB shows for TCLOO 1.0.2:
tclOODefineCmds.c:1188
oPtr->classPtr is NULL when the objdefine call is made.
That sounds like it might be a bug in the safety conditions for mutation. Which is unfortunate; the separate TclOO is archived as it won't be tracking even all the bugfixes in the Tcl 8.6 version of TclOO (let alone the new features in later Tcl versions). As the code works with 8.6.12, the suggested fix is not to use an end-of-life version series of Tcl; 8.6 receives bug fixes, 8.5 (and closely linked code such as the independent TclOO) does not.
This wasn't the answer you wanted, but it is the answer you'll get. (I'm not interested in hunting down when the bug was fixed, let alone backporting the fix to something I won't ever release.)