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. |