Expected Behaivor or bug (Stack with OOP-classes)?

Monkey Forums/Monkey Programming/Expected Behaivor or bug (Stack with OOP-classes)?

Wylaryzel(Posted 2014) [#1]
Dear monkeyX-users,

I getting more and more used to utilize the option that Stacks or Lists can have different classes as long as they are based on the same BaseClass.

But today I stumbled over an issue whereas I'm not sure if this is indended / bug or something on my end:

Example (my classes are a bit more complex):
Class Point
     Field x:Int
     Field y:Int

End

Class BouncingPoint extends Point
    Field bounce:Bool
End

Class Test
     Field testStack:Stack<Point> = New Stack<Point>

     Method AddPoint:Void(point:Point)
             Stack.Push(point)
     End
End


Now, if I want to access for example the 4 element of the stack which may was an BouncingPoint and retrieve the bounce-value, I can't!?!
if testStack.Get(3).bounce bla,bla
The compiler (for desktop at least) gives the following error:
Error:Identifier 'bounce' not found

Any ideas?

I mean, I could go around and assign the element to local var, but would that be efficient?

Thx in advance


muddy_shoes(Posted 2014) [#2]
The stack is storing and returning Point references. The Point class doesn't have a bounce field. You need to cast the reference or change the Stack declaration to use BouncingPoint.


Markus(Posted 2014) [#3]
maybe you mean this
Field testStack:Stack<BouncingPoint > = New Stack<BouncingPoint >
Stack.Push(point) ???
testStack.Push(point)


ziggy(Posted 2014) [#4]
Example on how to solve it:
local bpoint:BouncingPoint 

'This will try to convert the result of testStack.Get(3) to a BouncingPoint instance. If it fails, it will return null:
bpoint = BouncingPoint( testStack.Get(3) )

'Then we can do whatever with our bpoint variable, after checking it's not null:
if bpoint <> null then bpoint.bounce blah blah


Just a small sample which I hope makes things a nit easier to understand.


Markus(Posted 2014) [#5]
@ziggy
I see that differently.


AdamRedwoods(Posted 2014) [#6]
another, more complex, way:



Wylaryzel(Posted 2014) [#7]
Dear all,

as the OP I want to come back to this topic. The example I gave in the first post was only a very simple version what I'm doing with my entity and GUI system. The GUI system has a baseClass and several (unlimited) number of extended classes in itself. During the update or render method it cycles through all the attached classes (collected in a stack) as the basic drawing routines are sometimes the same - sometimes are different. Using an overwriting method works very well.

During some further thinking today I came to the similar conclusion as Adam with the difference that I implemented a method (instead of an interface) in the baseClass to change the value which returns a False (as there is no variable to be changed) and in the extended class an overwriting method which returns true,
Similar it would be returning Null if there is no value to grab and the value if it exists.

Its not to simple - but at least a solution.

But it still doesn't answer my question - as far as I understand I have a reference to the bouncingPoint in the stack. Why can't I access the value directly?

BR
Wyl


AdamRedwoods(Posted 2014) [#8]
as far as I understand I have a reference to the bouncingPoint in the stack. Why can't I access the value directly?

muddy_shoes answer:

The stack is storing and returning Point references. The Point class doesn't have a bounce field. You need to cast the reference or change the Stack declaration to use BouncingPoint.


...or another explanation:
BouncingPoint is a Point
Point is NOT a BouncingPoint (as BouncingPoint contains more information than Point)
Stack.Get(3) is a Point, but also a reference to a BouncingPoint. In order to tell the compiler it's a BouncingPoint, it must be dynamically casted.


Markus(Posted 2014) [#9]
i believe
Class BouncingPoint extends Point
means
the BouncingPoint include Point struct


Gerry Quinn(Posted 2014) [#10]
Yes, that is what is happening 'under the hood'. A Point object stores an x and a y, while a BouncingPoint object stores x, y and bounce. And there could be other extended point types that store other things, or have overridden methods etc.

The thing is, even if you know all the points you will be using are BouncingPoints, the compiler isn't clever enough to figure that out by itself, so you have to tell it - either by explicitly making a stack of BouncingPoints (but then you cannot legally put ordinary Points on it), or by casting an object from a Point stack to a BouncingPoint.

There are various ways and means of organising things like this - there is no one perfect way, and what is best depends on the situation.


Wylaryzel(Posted 2014) [#11]
please apologize if I bring this topic again on top, but this time I only want say thank you to all of you who helped me to understanding some of the pieces under the hood :-)