Self. inside a child extends class don't work
Monkey Forums/Monkey Programming/Self. inside a child extends class don't work
| ||
| Is this a bug ? The Self. inside a child (Extends) class don't work sometimes. In the example below its working only for the Field [test] but not for the Field [objs] I have found how to work with it, but I don't know if this is the best/fastest way to do it.
Class Blocks
Field objs:List<Block> = New List<Block>
Field test:Int = 2
End
Class Block Extends Blocks
Method OnUpdate:Int()
Print(Self.test) ' can show number 2 - is oke
For Local block:= Eachin Self.objs
Print("hey") ' does nothing !
Next
End Method
End
To fix this 'problem' I have to use a extra Field and give the parent class object when I create the child object. But will this slow down or give errors later ?
Class Blocks
Field objs:List<Block> = New List<Block>
Field test:Int = 2
End
Class Block Extends Blocks
Field parent:Blocks
Method New(inpParent:Blocks) ' give the parent
parent=inpParent
End Method
Method OnUpdate:Int()
Print(Self.test) ' can show number 2 - is oke
For Local block:= Eachin parent.objs
Print("hey") ' works !
Next
End Method
End
Thanks for the info |
| ||
Field objs:List<Block> = New List<Block> This line shouldn't work because you can't initialize an object at field declaration time. This will work. Class Blocks Field objs:List<Block> Field test:Int = 2 Method New() objs = New List<Block>() End End And even if you have a constructor for a class extending "Blocks", that constructor with no parameters will always be run from each class inherited. I'd also like to note that in your example, here For Local block:= Eachin Self.objs
Print("hey") ' does nothing !
NextThat there is nothing in it to begin with, so I don't see why it would do anything. Maybe you cut down the example too much. |
| ||
Oke I made a new example, btw the Field objs:List<Block> = New List<Block>does work, but I will change it your way. to make it future proof. You can copy/past this in monkey What I see now is 2 things - When creating a New Block() it triggers the parent class: New() This is a little weird because I'm creating a extended child class object, and don't want a new Parent object - the Self.objs inside the Extended class object still count 0 (but I made 2)
Strict
Import mojo
Class Blocks
Field objs:List<Block>
Field test:Int = 2
Field InternBlockCount:Int = 0
Method New()
Print("Create Class object Blocks")
objs = New List<Block>()
End
Method AddBlock:Void()
Print("Add a new block, count:"+objs.Count()) ' is oke
InternBlockCount = objs.Count()
objs.AddLast(New Block()) ' < this triggers the New() above !
End
Method OnUpdate:Int()
' update each block
For Local block:= Eachin objs
block.OnUpdate()
Next
' and do some other code...
' for example I want to create a new block here
' this is not the real code but for showing the problem I create 1 new block
If objs.Count()<=1
AddBlock() ' now I have 2 blocks, but still no printing ("Hey") below
Endif
Return 0
End
End
Class Block Extends Blocks
Field x:Float=20.0
Method New()
Print("Create Class object Block = correct")
End Method
Method OnUpdate:Int()
' Print(Self.test) ' can show number 2 - is oke
' Print(Self.objs.Count()) ' is not oke
' Print(Self.InternBlockCount) ' is not oke
For Local block:= Eachin Self.objs
Print("hey"+block.x) ' does nothing , when I have made blocks
Next
Return 0
End Method
End
'==========================================================
Class MyGame Extends App
Field Blocks:Blocks
Method OnCreate:Int()
' Startup code goes here
SetUpdateRate 60
Print("Create Game")
Blocks = New Blocks()
Blocks.AddBlock()
Return 0
End
Method OnUpdate:Int()
Blocks.OnUpdate()
Return 0
End
Method OnRender:Int()
Return 0
End
End
Function Main:Int()
New MyGame
Return 0
End
I think the first problem is because its a extened class, using the same method names (2times New()) I guess I don't want to use the extends and yust add a Field [parent] so it works. |
| ||
| This line shouldn't work because you can't initialize an object at field declaration time. Yes you can! Monkey does cleverly execute initializaion of fields just before calling New, so this is perfectly valid on Monkey.See example (stdcpp) : Function Main() New Manel End Class Manel Field myfield:List<String> = New List<String> Method New() Print myfield.Count() End End The problem is,as you say, that the above code is iterating the contents of an empty list, so no items to iterate. The "for" block does never execute. |
| ||
I see, the error is that you are not filling the objs field of each child blocks, but you're pretending an interation throug them. each class instance has its own instances of each field. If you want the objs field to be "shared" in all classes instances and child classes, you should declare this field as a global inside the class:Strict
Import mojo
Class Blocks
Global objs:List<Block> 'This does not deppend on classes instances or inheritance. It's just a global.
Field test:Int = 2
Field InternBlockCount:Int = 0
Method New()
Print("Create Class object Blocks")
If objs = Null then objs = New List<Block>()
End
Method AddBlock:Void()
Print("Add a new block, count:"+objs.Count()) ' is oke
InternBlockCount = objs.Count()
objs.AddLast(New Block()) ' < this triggers the New() above !
End
Method OnUpdate:Int()
' update each block
For Local block:= Eachin objs
block.OnUpdate()
Next
' and do some other code...
' for example I want to create a new block here
' this is not the real code but for showing the problem I create 1 new block
If objs.Count()<=1
AddBlock() ' now I have 2 blocks, but still no printing ("Hey") below
Endif
Return 0
End
End
Class Block Extends Blocks
Field x:Float=20.0
Method New()
Print("Create Class object Block = correct")
End Method
Method OnUpdate:Int()
' Print(Self.test) ' can show number 2 - is oke
' Print(Self.objs.Count()) ' is not oke
' Print(Self.InternBlockCount) ' is not oke
For Local block:= Eachin Self.objs
Print("hey"+block.x) ' does nothing , when I have made blocks
Next
Return 0
End Method
End
'==========================================================
Class MyGame Extends App
Field Blocks:Blocks
Method OnCreate:Int()
' Startup code goes here
SetUpdateRate 60
Print("Create Game")
Blocks = New Blocks()
Blocks.AddBlock()
Return 0
End
Method OnUpdate:Int()
Blocks.OnUpdate()
Return 0
End
Method OnRender:Int()
Return 0
End
End
Function Main:Int()
New MyGame
Return 0
End |
| ||
| A little hard to understand because I can't see the differents between Field test:Int = 2 and Global objs:List<Block> or Field objs:List<Block> Is it like this: [Blocks] --test=1 --objs ---[ block ] ---[ block ] ---- this block can't see all [Blocks.objs] because its created like **1 ---[ block ] **1 [Blocks] --test=1 --objs (none at initalization) uuuh well i can't explain it but I think I get it. I will make it global and use my first syntaxt creating a field like this: Field objs:List<Block> = New List<Block>()so I don't have to use the null code inside the New() And I learned now that New() is triggerd everytime I create a extended class object |
| ||
| A Global inside a class does not tie to the class instance. Example:
Class MyClass
Global MyGlobal:String = "Hello world!"
End Class
Function Main()
Print MyClass.MyGlobal
End FunctionSee that we do not even need to create an object instance for this to work. In other words, if you want to have ONE list with all objects, it has to be a global. Otherwise each object has its own list (in its own field). |
| ||
| I think the problem is that a lot of developers who are new to the OO paradigm don't recognise the difference between "class" and "instance". This might be a way to visualise it: Think of a class as a rubber stamp, and an ink mark as an instance. If I cut a line in the rubber (think "field"), it'll show up every time you "stamp" it. If I put a sticker on the handle of the stamp (think "global") it belongs to the stamp itself and doesn't affect what's on the paper. |
| ||
| Most of this confusion would be solved if self was mandatory for instance-member access and classname was mandatory for shared-member access. |