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 ! Next That 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 Function See 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. |