When I call MooRoot(1, "Jessie");, the output looks like:
MooRoot new Jessie
MooRoot init nil
MooRoot init Jessie
-> a MooRoot
It invokes the init method twice, once with nil arguments. This seems wildly wrong, but I can’t see what mistake I’ve made. How can I force it to only call init one time with the correct arguments?
Better is to avoid using init methods where possible and put all the logic into the constructor before you actually make the object. Most of the time, you can initialise the members and after construct them into an object.
Once this little fix for superPerformArgs is merged to.
you will be able to do this clever pattern that python does…
Base {
var a, b;
*new { | a, b ...args, kwargs|
// Something with a and b
^superPerformArgs(\newCopyArgs, [a, b] ++ args, kwargs)
}
}
Child: Base {
var c, d;
*new { |...args, kwargs|
// See if c or d was passed and do something with them.
^superPerformArgs(\new, args, kwargs)
}
}
Now you can call it like this…
Child(a: 1, b: 2, d: 4) // leaving c at nil
Just to answer this thread directly, you only need init methods when you must initialise ‘a’ and ‘b’ before ‘c’ and ‘d’. Generally that coupling is best avoided, but occasionally it is needed and init methods are one way to do it. It’s just they are very powerful but hard to manage at scale, particularly when you have multiple constructors and deep inheritance trees - its like use a jack hammer to open a bottle, only occasionally necessary.