This site requires JavaScript, please enable it in your browser!
Greenfoot back
ez4u2c
ez4u2c wrote ...

2011/9/17

Struggling with objects - (typecasting?)

ez4u2c ez4u2c

2011/9/17

#
In reading the tutorial 6 "How to access one object from another", in the hitAnAsteroid() method, there is a line of code:
    Space spaceWorld = (Space) getWorld();  // get a reference to the world
I think I understand that an object variable of type Space is declared and assigned the value returned from getWorld(). What has me somewhat puzzled is the word (Space) in parenthesis. This looks as though the value returned from getWorld() is being typecast as Space.class, but I don't understand why this is necessary so it must mean something else that escapes me.
davmac davmac

2011/9/17

#
Well, you could try removing it and see what happens :) What declared type does getWorld() return? (check the documentation) - it's "World". Now, it just so happens that we know the world is actually a "Space", but the compiler isn't aware of that (or, to put it another way, it believes there is a possibility that the world might in fact not be a Space - which is true; because you could create another World subclass and place your object in that!). So, without the typecast, you'll get an error when you compile. So, "(Space) getWorld()" means, roughly speaking: call getWorld(), and even though the declared return type of getWorld() is "World", I know in this case that it will really return a "Space".
ez4u2c ez4u2c

2011/9/17

#
So if I understand correctly: The variable spaceWorld which has already been declared to be of the type Space.class, could possibly be assigned something *other* than an object of type Space.class (assuming another World subclass object existed)? (BTW, thanks for your help with my education ;-)
davmac davmac

2011/9/17

#
So if I understand correctly: The variable spaceWorld which has already been declared to be of the type Space.class, could possibly be assigned something *other* than an object of type Space.class (assuming another World subclass object existed)?
If it's declared to be of type "Space", then it can reference an object of type Space or any subclass of Space, but not any other subclass of World.
ez4u2c ez4u2c

2011/9/17

#
Since Space is a subclass of World, it would follow that were that same line of code to read:
World spaceWorld = (Space) getWorld();  // get a reference to the world
then it should compile and spaceWorld should have all the attributes and methods provided by the World.class to the Space.class object returned by getWorld() but with the Space.class extensions amputated, no?
davmac davmac

2011/9/18

#
Well, yes, but you don't need the cast in that case; this does the same:
World spaceWorld = getWorld();  // get a reference to the world 
"getWorld()" already returns World, so there is no need for casting. As you're suggesting, you couldn't then call methods that are specific to Space.
ez4u2c ez4u2c

2011/9/18

#
So then typecasting an object's assignment can never yield greater capacity than the object's declared class provides (hence typecasting as a descendant class is meaningless), and the default type is the ancestor, which would seem to militate against the declaration. I guess I still don't see the rationale for this behaviour. Is this a java characteristic or peculiar to Greenfoot? (I must confess to being a Borland Pascal aficionado, which may help to explain some of my predilections) Thank you for any insight you may be willing to share as I attempt to orient my program objectively.
davmac davmac

2011/9/18

#
So then typecasting an object's assignment can never yield greater capacity than the object's declared class provides (hence typecasting as a descendant class is meaningless)
Can you give an example (i.e. code) of what you mean?
and the default type is the ancestor, which would seem to militate against the declaration
I'm not sure what you mean by this either, sorry.
Is this a java characteristic or peculiar to Greenfoot?
It's a characteristic of Java. The language you code in when you use Greenfoot is Java; no more, no less.
ez4u2c ez4u2c

2011/9/18

#
An example of futile typecasting as a descendant class (extensions are lost):
World spaceWorld = (Space) getWorld();  // get a reference to the world
And an example of the default (no typecast) returning the ancestor (World),:
Space spaceWorld = getWorld();  // get a reference to the world
instead of returning the declared subclass Space, which the object is already declared to be. So it would seem there *must* be some advantage to having the compiler ignore the declaration in determining which class/subclass of World to return, necessitating the seemingly redundant typecast of getWorld(), which at present just escapes me.
davmac davmac

2011/9/18

#
An example of futile typecasting as a descendant class (extensions are lost):
Ok, you're correct that in this case the cast is pointless. (It is still not completely meaningless - the cast will be checked at runtime, and an exception will be thrown getWorld() returns something that is not a Space; but this usage is uncommon).
And an example of the default (no typecast) returning the ancestor (World),:
The "getWorld()" method call results in an expression of type World, because that is what it is declared to return. This particular example you have given would not compile, because the compiler sees that you have tried to assign something which (as far as it is concerned) could be an instance of any subclass of World, to a variable "spaceWorld" of type Space, which may not be correct. The error is warning you of this. The typecast is your way of informing the compiler that you are aware of the mismatch and you know what you are doing.
... instead of returning the declared subclass Space, which the object is already declared to be. So it would seem there *must* be some advantage to having the compiler ignore the declaration in determining which class/subclass of World to return, necessitating the seemingly redundant typecast of getWorld(), which at present just escapes me.
The advantage is that the compiler is able to diagnose and prevent a certain class of error - accidentally assigning an object reference to a variable of the wrong type.
You need to login to post a reply.