class ClassA:
def __init__(self):
self.x = 1
class ClassB(ClassA):
def __init__(self):
ClassA.__init__(self)
self.y = 1
b = ClassB()
print "x =", b.x, "y =", b.y
output: x = 1 y = 1
So for now I made this:
type
# parent object
PObjectA = ref TObjectA
TObjectA = object of TObject
x: int
# child object
PObjectB = ref TObjectB
TObjectB = object of TObjectA
y: int
# parent object constructor
proc newObjectA(child: PObjectA = nil): PObjectA =
if child == nil: new(result) # if creates a new object
else: result = child # if ref to child provided
# init object fields
result.x = 1
# child object constructor
proc newObjectB(child: PObjectB = nil): PObjectB =
if child == nil: new(result)
else: result = child
discard newObjectA(result) # calling parent object consructor
# init object fields
result.y = 2
var b: PObjectB = newObjectB()
echo("x=", b.x, " y=", b.y)
output: x=1 y=2
But don't I miss some easier way to do this?
type
PObjectA = ref TObjectA
TObjectA = object of TObject
x: int
PObjectB = ref TObjectB
TObjectB = object of TObjectA
y: int
proc initA(a: PObjectA) =
a.x = 1
# parent object constructor
proc newObjectA(): PObjectA =
new(result)
initA(result)
# child object constructor
proc newObjectB(): PObjectB =
new(result)
initA(result)
# init object fields
result.y = 2
var b = newObjectB()
echo("x=", b.x, " y=", b.y)
Thanks for reply.
Also I've got a related question. When I try to call base class method I get segmentation fault. It seems that this is not the right way to do it:
type
PObjectA = ref TObjectA
TObjectA = object of TObject
PObjectB = ref TObjectB
TObjectB = object of TObjectA
method update(obj: PObjectA) =
echo("update parent")
method update(obj: PObjectB) =
#PObjectA(obj).update() # This is causes a segfault
echo("update child")
proc newObjectA(): PObjectA =
new(result)
proc newObjectB(): PObjectB =
new(result)
var x: PObjectA = newObjectB()
x.update()
method update(obj: PObjectB) =
PObjectA(obj).update()
Your explicit type conversion does not inhibit dynamic binding so you create an endless recursion here, causing a stack overflow and thus a segfault. Again, to get "super"-like functionality, you need to use a helper proc:
type
PObjectA = ref TObjectA
TObjectA = object of TObject
PObjectB = ref TObjectB
TObjectB = object of TObjectA
proc updateA(obj: PObjectA) =
echo "update parent"
method update(obj: PObjectA) =
updateA(obj)
method update(obj: PObjectB) =
updateA(obj)
proc newObjectA(): PObjectA =
new(result)
proc newObjectB(): PObjectB =
new(result)
var x: PObjectA = newObjectB()
x.update()
Your explicit type conversion does not inhibit dynamic binding so you create an endless recursion here, causing a stack overflow and thus a segfault
Should a thing like this be detected at compile time? Or at least raise another exception other than SIGSEGV?
Detecting this at compile time seems hard. I'm still thinking about how to improve it.
Detecting stack overflows at runtime properly is also non-trivial; previous attempts never really worked: It's hard (but not impossible) to call a stack overflow handler when there is no space left in the stack. :D
Hello,
I just discovered Nimrod and I like many aspects of it, but it seems that object oriented code will be very verbose if this example is any indication: I think that the equivalent code in Scala would be much, much shorter (Python's initial example is already terser than Nimrod)..
I'm a bit worried by this aspect of Nimrod..
BR, renoX
It's possible to design a 'class' macro but nobody ever wrote it. :-)
# implementation left as an exercise for the reader
import classes
class MyClass(refsemantics):
proc init() =
x = 3 # 'class' could make implicit field definitions possible
method doIt() =
# aka 'virtual'
echo "do it"
It's possible to design a 'class' macro but nobody ever wrote it.
To study what would be a good design, why not? But for a "base" feature in the end, it must be built-in in the language otherwise it will make debugging more difficult (thinking long term with a "native" compiler).