Like this:
type
SuperClass =
ref object {.inheritable.}
x: int
Subclass =
ref object of SuperClass
y: int
proc init(self: SuperClass) =
self.x = 1
proc init(self: SubClass) =
init(self.SuperClass)
self.y = 2
template defaultConstructor =
new(result)
init(result)
proc initSuperClass: SuperClass = defaultConstructor
proc initSubClass: SubClass = defaultConstructor
echo repr(initSuperClass())
echo repr(initSubClass())
Jehnan,
If I extend the class hierarchy one more level as below it appears that the 'x' member of the SuperClass goes missing.
type
SuperClass =
ref object {.inheritable.}
x: int
Subclass =
ref object of SuperClass
y: int
Subclass2 =
ref object of SubClass
z: int
#method init(self: SuperClass) = #stack overflow entering init(SubClass2)
proc init(self: SuperClass) =
echo "Entering init(SuperClass) ", repr(self)
self.x = 1
echo "Exiting init(SuperClass) ", repr(self)
#method init(self: SubClass) = #stack overflow entering init(SubClass2)
proc init(self: SubClass) =
echo "Entering init(SubClass) ", repr(self)
init(self.SuperClass)
self.y = 2
echo "Exiting init(SubClass) ", repr(self)
#method init(self: SubClass2) = #stack overflow entering init(SubClass2)
proc init(self: SubClass2) =
echo "Entering init(SubClass2) ", repr(self)
init(self.SubClass)
self.z = 3
echo "Exiting init(SubClass2) ", repr(self)
template defaultConstructor =
new(result)
init(result)
proc initSuperClass: SuperClass = defaultConstructor
proc initSubClass: SubClass = defaultConstructor
proc initSubClass2: SubClass2 = defaultConstructor
echo "Calling initSubClass2 ", repr(initSubClass2())
The output from the code above where the init() for SuperClass executes but there is no 'x' member
Entering init(SubClass2) ref 0x7ffbf70cc050 --> [z = 0, y = 0] Entering init(SubClass) ref 0x7ffbf70cc050 --> [z = 0, y = 0] Entering init(SuperClass) ref 0x7ffbf70cc050 --> [z = 0, y = 0] Exiting init(SuperClass) ref 0x7ffbf70cc050 --> [z = 0, y = 0] Exiting init(SubClass) ref 0x7ffbf70cc050 --> [z = 0, y = 2] Exiting init(SubClass2) ref 0x7ffbf70cc050 --> [z = 3, y = 2] Calling initSubClass2 ref 0x7ffbf70cc050 --> [z = 3, y = 2]
This seems to be a bug in repr(). The following works:
let zz = initSubClass2()
for name, val in zz[].fieldPairs:
echo name, ": ", val
Jehan,
Thanks for your expert help. My apologies for the typo in your name in the previous post.
How should a report for the repr() bug be made? This bug can lead to considerable confusion for users.
You could always use the OOP macro on https://nim-by-example.github.io/oop_macro/ as well.
Or my modified version here, which allows for inheritance: https://github.com/jyapayne/nim-extensions/blob/master/oop_macro.nim
Hi Jehan and jyapayne,
I finally registered for github and reported the repr() issue as " repr() misses base object field in 2nd level derived object #2749"
Regarding jyapayne's oop_macro.nim, is there a reason that the "super" functionality is commented out and supplanted by the mechanism for "procName_ClassName()" substitution?
I ask as Python programmers are accustomed to using "super()" to access parent class methods without specifying the specific parent class name. For NIM with its single inherentance, there wouldn't seem to be an issue with parent class resolution.
Nim has single inheritance, but multiple dispatch, which complicates things a bit. For now you can use procCall:
method foo(x: SuperClass) = echo "foo"
method foo(x: SubClass) =
procCall foo(x.SuperClass)
echo "... inherited"
method foo(x: SubClass2) =
procCall foo(x.SubClass)
echo "... twice"
foo(SubClass2())
What procCall does is to suppress dynamic dispatch based on the actual types of the arguments and instead calls the method based on the declared types.