Hi all, Please see this code. I somehow managed to access base class member from child class, by giving the base as parameter in child's ctor. See this code. But i cant access the base class member from instantiated child variable.
type
BaseWindow = ref object of RootObj
title : string
width : int
height : int
windowCount : int
windowList : seq[int]
ChildWindow = object of BaseWindow
handle : int
proc NewBaseWindow*(title : string = "My New window") : BaseWindow =
result = new BaseWindow
result.title = title
result.width = 800
result.height = 600
result.windowCount = 0
result.windowList = @[]
# Child class ctor is taking base class as param. Without this, i cant access base members.
# Please tell me that, is there a better way to do this.
proc NewChildWindow*(base : BaseWindow) : ChildWindow =
base.windowCount.inc() # Want to modify base class member
base.windowList.add(base.windowCount) # Want to modify base class member
echo "Created a Window"
echo "Title = ", base.title # Want to access base class member
echo "Width = ", base.width # Want to access base class member
echo "Height = ", base.height # Want to access base class member
var bw = NewBaseWindow()
var cw = NewChildWindow(bw)
echo cw.windowList.len # Want to access base class member, but can't. Please help.
I have got a work around. See this ; I just add a variable which contain the whole base class.
type
BaseWindow = ref object of RootObj
title : string
width : int
height : int
windowCount : int
windowList : seq[int]
ChildWindow = object of BaseWindow
handle : int
parent : BaseWindow
Now, i can easily access the base class members
proc NewChildWindow*(base : BaseWindow) : ChildWindow =
result.parent = base
result.parent.windowCount.inc()
result.parent.windowList.add(result.parent.windowCount)
echo "Created a Window"
echo "Title = ", base.title
echo "Width = ", base.width
echo "Height = ", base.height
Now, i can easily access base members like this
var bw = NewBaseWindow()
var cw = NewChildWindow(bw)
echo cw.parent.windowList , " -- At Last i got it"
echo bw.windowList, " -- Same data"
Is it a good practice ?You never modify the result or return anything in NewChildWindow. And since ChildWindow is an object and not a ref object, it will initialize all its fields to their default values which is why cw has no children.
I think what you want to do is in line with the super constructor calls in normal OOP languages, but this is not possible in Nim due to object slicing going away and the constructor pattern in Nim (newObj) being to create objects in the constructor instead of modifying a parameter. The solution I can give you doesn't have object inheritance and is a bit more idiomatic:
type
Window = ref object
title: string
width, height: int
children: seq[int]
ChildWindow = object
window, parent: Window
handle: int
proc newWindow*(title: string = "My New window"): Window =
new(result)
result.title = title
result.width = 800
result.height = 600
result.children = @[]
proc addChild*(parent, window: Window): ChildWindow =
result.parent = parent
result.window = window
result.handle = parent.children.len + 1
parent.children.add(result.handle)
var bw = newWindow()
var cw = bw.addChild(newWindow("My new child window"))
echo bw.children.len # 1
echo cw.parent.children.len # 1
echo cw.window.title # My new child window
2. You suggested to including base type in child type as member is a good idea. Ok, but is there any overhead problems in it ? For example, i only need the parent window handle from child class. To obtain that, including the whole parent class in derived class is a good idea ? or is there any alternate options for it ?
You may also compare your code with this example of OOP inheritance:
https://forum.nim-lang.org/t/4226
The corrected code of lscrd should compile and work.
I think your own code on the top is a bit "strange and dangerous" as you manually initialize member fields of your base class in you child classes. I think it is more clean to have an init proc for base class, so you call this first, then initialize the new fields of your child class. Note that your base class may be even located in another module and base class implementation may change without notice in general case.
Sure, i will read it. >I think your own code on the top is a bit "strange and dangerous"
I will check what i can do in that case. Thanks for pointing me the right direction.