The direct way to separate the parent's initialization is not use methods since
there's no need for dynamic dispatch, even though an OOP language would use
super in such a case:
type
ParentObj* = ref object of RootObj
parentField: int
ChildObj* = ref object of ParentObj
childField: int
proc init*(parent: ParentObj, n: int) =
parent.parentField = n
proc init*(child: ChildObj, n: int) =
child.ParentObj.init(123)
child.childField = n
proc newChild*(value: int): ChildObj =
new result
result.init(value)
var child = newChild 567
echo "child parentField: ", child.childField
echo "child childField: ", child.parentField
Run
What `procCall` is for, is these circumstances where some specific resolution
is static and known, but where you're using methods because the resolution is
usually dynamic. I can't think of a good example of that, so here's typical
OO-example fare:
import std/sequtils
type
Animal = ref object of RootObj
noisiness: int
Dog = ref object of Animal
method bark(a: Animal) {.base.} =
inc a.noisiness
method bark(a: Dog) =
echo "A dog barks"
procCall bark(Animal(a))
proc thunder(area: var seq[Animal]) =
for animal in area:
animal.bark()
# late addition
type Cat = ref object of Animal
method bark(a: Cat) =
echo "A cat meows"
procCall bark(Animal(a))
var area: seq[Animal] = @[new Dog, new Dog, new Cat]
thunder area
thunder area
thunder area
echo "Noisiness: ", area.foldl(a+b.noisiness, 0)
Run