Array of objects of a subtype not OK?

Monkey Forums/Monkey Programming/Array of objects of a subtype not OK?

Tibit(Posted 2012) [#1]
This does not work:
[monkeycode]
Class Shape

End

Class Circle Extends Shape

End

Class Camera

Method New(shapes:Shape[])
Print "Length is " + shapes.Length
End
End

Function Main:Int()

Local circle1:Circle = New Circle
Local circle2:Circle = New Circle

Local test:Camera = New Camera([circle1, circle2]) 'Compile error here:
': Error : Unable to find overload for new(Circle[]).


End
[/monkeycode]

Can it be done somehow? Or should I use some kind of list?

I really liked the idea of auto-arrays like this since it is super handy when setting things up.


Gerry Quinn(Posted 2012) [#2]
Seems like it should work, but the compiler is not smart enough to figure it out.


Tibit(Posted 2012) [#3]
Ah cool!

I added a bug report in case it is unintended. Hoping for the best.


marksibly(Posted 2012) [#4]
Hi,

It's by design, basically to avoid the overhead of having to check the actual type of objects assigned to array elements at runtime.

It means you can't accidentally do this:

Class Shape
End

Class Circle Extends Shape
End

Class Square Extends Shape
End

Function Test( shapes:Shapes[] )
   shapes[0]=New Circle   'perfectly valid code...
   shapes[1]=New Square   'ditto
End

Function Main()
   Test( New Shape[2] )   'OK
   Test( New Circle[2] )  'OOPS! Test will put a Square into our Circle array!
   Test( New Square[2] )  'OOPS2!
End


If Monkey allowed Circle[]/Square[] to Shape[] conversions like this, then it'd have to perform a runtime check every time an object was written to Shape[] arrays to make sure the type of the object being written was a subclass of the 'real' type of the array.

Java and C# actually already do this assignment checking, but emulating it in other languages is harder. Apart from the overhead of the checks, it'd also mean object arrays would have to be 'wrapped' to include some runtime type info, so even all reads would be affected by an extra level of indirection.

BlitzMax (and probably Blitz3D/BlitzPlus) just ignore this issue, so it's actually possible to put a Square into a Circle[] in those languages! But I decided in Monkey to just prohibit implicit array casting like this and see what happened. So far, people seem to have been able to work around it and the issue seldom comes up...


Tibit(Posted 2012) [#5]
I agree it is very rare, never encountered it myself, until I got the idea to use arrays more.

I fear I might misunderstand the bottom line, however in my case above - would it not just be enough if the auto-declared array [] was assumed to be of the assigning type?

Local a:= [Circle,Circle2]
a is a Circle[], as expected

Local a:Shape[] = [Circle,Circle2]
Here since Circle and Circle2 are shapes - which is what we want, can it not be assumed that the autoArray of two Circles actually is a ShapeArray?
Could not this pass runtime? Since Circle & Circle2 will always Inherit from Shape, and that won't change runtime at least.

I 100% agree with the argument to not do a runtime check every time. And I'm pretty fine with not having type-casting on arrays, but letting those correct auto-created arrays [1,2,2,3] trough would be quite useful I think!


muddy_shoes(Posted 2012) [#6]
No comment.


dmaz(Posted 2012) [#7]
I say ignore the issue and do it like bmax... let the programer be responsible (a compile warning would be cool though). the "work around" add to much more code for what gain? and they tend to be a little ugly too.


ziggy(Posted 2012) [#8]
I would not make it like BlitzMax (in fact, I would suggest a BlitzMax fix) as having a parent object into an object array is undesirable. That said, allowing a runtime check would be cool as in C# and Java would be cool, but I'm not sure wich performance costs this will add on other targets.


Gerry Quinn(Posted 2012) [#9]
I've always disliked that in Java you can't just cast anything to anything like in C++. But given that it's one of the target languages, it seems like it would be inviting trouble to let Monkey cast freely in ways that would work on some targets and not on others.

I know muddy is thinking of another issue that came up lately in which functions with side effects are getting discarded by the compiler. But short of adding C++ code for run-time type checking, which would be a lot of work for a small improvement, I think Mark may have the most pragmatic solution here.

I could be wrong - I guess whether things like this come up often depends on your programming style, and run-time polymorphism is not a big part of mine.


muddy_shoes(Posted 2012) [#10]
Nope. I'm thinking of the fact that this exact same issue has been raised multiple times already and the various demonstrations that spending effort expressing views here is wasted.

here: http://www.monkeycoder.co.nz/Community/posts.php?topic=2879#31930