Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

did not understand tcl oo mixin

234 views
Skip to first unread message

tombert

unread,
Apr 16, 2013, 11:21:13 AM4/16/13
to
Considering the following example:

oo::class create B {
variable bvar
constructor args {set bvar "fromB"}
method getBvar args {return $bvar}
}

oo::class create A {
mixin B
variable avar
constructor args {set avar "fromA"}
method getAvar args {return $avar}
}

The problem: The object from class A cannot access its variables any more:

> set a [A new]
::oo::Obj95
> $a getAvar
can't read "avar": no such variable

It obviously works using "superclass" instead of "mixin". But "mixin" should add additional classes without influencing its own content??

thx

Donal K. Fellows

unread,
Apr 17, 2013, 8:56:30 AM4/17/13
to
On 16/04/2013 16:21, tombert wrote:
> The problem: The object from class A cannot access its variables any more:
>
> % set a [A new]
> ::oo::Obj95
> % $a getAvar
> can't read "avar": no such variable
>
> It obviously works using "superclass" instead of "mixin". But "mixin"
> should add additional classes without influencing its own content??

I confirm that I can reproduce this, and that it looks like either a bug
or a "surprising" consequence. I don't like "surprising"; I need to
check whether the running of class-level mixins' constructors was a
deliberate change or an unintentional one.

Donal.
--
Donal Fellows — Tcl user, Tcl maintainer, TIP editor.

gustafn

unread,
Apr 20, 2013, 5:02:21 AM4/20/13
to
Since I am not sure about the intended semantics of constructors in tcloo, let me rephrase the example in nx (http://next-scripting.org):

nx::Class create B {
:method init {} {set :bvar "fromB";next}
:public method getBvar args {return ${:bvar}}
}
nx::Class create A {
:mixin B
:method init {} {set :avar "fromA"}
:public method getAvar args {return ${:avar}}
}

In nx, the constructor is a method named "init". When a mixin is used in class A, the methods of the mixin B can potentially shadow all methods of A. The reason for this is that a mixin in xotcl/tcloo/nx is used as a decorator rather than a Ruby-style "mixin module" (see for the differences https://next-scripting.org/xowiki/file/docs/nx/examples/ruby-mixins.html?html-content=1).

With a decorator mixin, the methods mixed-in can redefine the full behavior. In other words, the mixin has a higher precedence than the intrinsic classes. By using "info precedence"

set a [A new]
puts [$a info precedence]

one can see that B put into the precedence order before A, therefore the constructor of B requires a "next". On the contrary, when B is defined as superclass of A, the precedence order lists A before B, so there is no need for a "next" just to initialize "avar", but one will face the same problem with "bvar".

With nx, there is as well the option to initialize variables without constructor to avoid such problems at all. In nx, the default values for instance variables can be defined in a declarative way, using internally the same mechanism as method parameter.

nx::Class create B {
:variable bvar fromB
:public method getBvar args {return ${:bvar}}
}
nx::Class create A {
:mixin B
:variable avar fromA
:public method getAvar args {return ${:avar}}
}
set a [A new]
puts [$a getAvar]

This avoids the need of using constructors for such cases at all and provides more symmetry for different class composition techniques. Hope, this brings some insights....

all the best
-gustaf neumann

tombert

unread,
Apr 22, 2013, 5:06:54 AM4/22/13
to
Thx for both clarifications. I did not thought that the order of constructors is changed using "mixin". The "next" in the class B looks unlogic to me ...

If I should write a bug-report let me know.

Regards

gustafn

unread,
Apr 22, 2013, 1:19:36 PM4/22/13
to
On Monday, April 22, 2013 11:06:54 AM UTC+2, tombert wrote:
> Thx for both clarifications. I did not thought that the order of constructors is changed using "mixin". The "next" in the class B looks unlogic to me ...

note that by the decorator logic, all methods of the base class can be potentially shadowed by a mixin class. The constructors and destructors are methods as well. In a complex compositions, it quite nice to provide different constructors (e.g. for object persistence).

Also the tcloo man page says "Within the constructor, the next command should be used to call the superclasses' constructors." So, i see no reason, why this should be different for constructors/destructors of mixin classes.

In general is the issue of state management for mixin classes a complex one, purely behavioral mixin classes require less thought.

tombert

unread,
Apr 23, 2013, 5:32:30 AM4/23/13
to
ok - understood - thx.
0 new messages