If I have classes A & B, and a class C that inherits from them, how can
I call the constructors of A & B with the correct arguments?
oo::class create C {
supperclass A B
constructor {arg_for_A arg_for_B} {
call constructor of A
call constructor of B
initialise C
}
}
Any ideas?
George
The [next] command. It calls the 'next' constructor in the chain of
them. There's a linearization algorithm applied to flatten the graph
of implementations of constructors (it's the same as the one used for
methods, except filters aren't called and there can't be any per-
object mixins at this stage). The algorithm - which is the same as the
one used by XOTcl, as it happens - is correct, but very confusing in
some cases. I spent a lot of time working through examples to figure
out what I wanted to happen, and it's a fair chunk of why TclOO took a
long time to write. To work out whether A's or B's constructor is
chained to first, the easiest way is to just test it. If you've got
complicated argument passing getting in your way, you've probably got
the wrong design (i.e., your code is probably getting cleverer than
you; do something simpler before it tries to take over the world!)
Experimenting (and showing how to use [next]) on a classic diamond
class structure:
$ tclsh8.5
% package require TclOO
0.6.2
% oo::class create A {constructor x {puts A::$x}}
::A
% oo::class create B {
superclass A
constructor {x args} {puts B::$x;next {*}$args}
}
::B
% oo::class create C {
superclass A
constructor {x args} {puts C::$x;next {*}$args}
}
::C
% oo::class create D {
superclass B C
constructor {x args} {puts D::$x;next {*}$args}
}
::D
% D new 1 2 3 4
D::1
B::2
C::3
A::4
::oo::Obj8
I think it's probably easier if you can use key-value arguments when
passing values into such a complex system.
Donal.
Dear Donal,
I am not concerned about the execution order of the constructors (it
doesn't matter in my case), but rather the fact that they accept a
different number of arguments. In this case, how a call to next can be
written? Will the next invoking algorithm select the appropriate
constructor based on the number of arguments, and I have to call two
next with a different set of arguments?
The problem I think is that the two classes I want to mix do not belong
into the same hierarchy. What I am trying to do, is similar to the
following:
I have a class A, that is a tree widget.
I have a class B, that is a list widget.
Now I want to make a new class C, that is a file explorer.
(Ok, I don't want to do this, but you get the idea).
One of the ways to do it, is to inherit both A & B).
Lets assume that both A & C take as argument the path of the widget to
be built. The constructor of C accepts the path .fexp. How the
constructor of A can be called with the argument .fexp.tree and the
constructor of B with .fexp.list?
George
I think you need to re-examine your design. Surely you want to use
composition instead of inheritance.
> Lets assume that both A & C take as argument the path of the widget to
> be built. The constructor of C accepts the path .fexp. How the
> constructor of A can be called with the argument .fexp.tree and the
> constructor of B with .fexp.list?
oo::class create C path {
variable widgets
constructor {path} {
dict set widgets tree [A new ${path}.tree]
dict set widgets list [B new ${path}.list]
# ...
}
}
--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous
I know it is feasible with aggregation, but the concept that will
aggregate the two concepts must be re-implement all public methods of
both aggregated classes. This is not required if inheritance is used...
George