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

2011/9/25

How to create a persistent global object reference?

ez4u2c ez4u2c

2011/9/25

#
I would like to make a persistent reference to my world that my actor's methods can use to access my world's methods & variables without having to re-define the world object each time it's used. What I've tried so far compiles okay but gives a runtime error (null pointer). First I tried making a world variable and assigning it at once:
1
2
3
public class Wombat extends Actor
{
    private WombatWorld MyWorld = (WombatWorld) getWorld();
Next, I tried deferring the assignment until the actor's constructor is called:
1
2
3
4
5
6
7
public class Wombat extends Actor
{
    private WombatWorld MyWorld ;
     
    public Wombat()  {
        MyWorld = (WombatWorld) getWorld();
    }
Neither of these attempts were successful of course. Can anyone help me avoid having to re-declare my world object in every method that needs to reference one of it's methods?
kiarocks kiarocks

2011/9/25

#
This code should work:
1
2
3
4
5
6
7
8
9
10
11
12
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
 
public class Wombat extends Actor
{
    private WombatWorld MyWorld = (WombatWorld) getWorld(); 
     
    public void act()
    {
        
    }   
}
ez4u2c ez4u2c

2011/9/25

#
This compiles okay, but when one of Wombat's methods tries to use it (at runtime) it gets a null pointer exception. For example: lets say I have an actor class Spot, instantiated in the constructor of WombatWorld with a private variable name (private to WombatWorld), with a public method to return the spot object, called getSpot(). if Wombat has a method that calls getSpot() using MyWorld, it returns a null pointer at runtime. Here's a couple snippets, one from WombatWorld:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class WombatWorld extends World
{
    private Spot theSpot;
 
    public WombatWorld()  {
        super(8, 8, 60);       
        theSpot = new Spot();
        addObject(theSpot, 0, 0);
    }
 
    public Spot getSpot()  {
        return theSpot;
    }
...and one from Wombat:
1
2
3
4
5
6
7
8
public class Wombat extends Actor 
    private WombatWorld MyWorld = (WombatWorld) getWorld();
 
    private boolean onSpot()  {
        Spot spot = MyWorld.getSpot();
        return ((getX() == spot.getX()) && (getY() == spot.getY()));
    }
The null pointer exception occurs line #6 in Wombat. Why doesn't it work?
davmac davmac

2011/9/25

#
Why doesn't it work?
The "getWorld()" method returns the world that the actor is in - if any. If the actor isn't in the world yet, getWorld() returns null. In your example Wombat class above, getWorld() is being called on line 3, which runs when the Wombat is constructed - i.e. before it is actually put in the world. You can override the addedToWorld method to get a reference to the world when the actor is added to it:
1
2
3
4
protected void addedToWorld(World theWorld)
{
    myWorld = theWorld;
}
Note I wrote 'myWorld' not 'MyWorld', because in Java the convention is to have variable names start with lower-case letters (and class names start with upper-case letters).
ez4u2c ez4u2c

2011/9/26

#
I just uploaded my scenario as "wombat-spot" with the tag "test", for your perusal. It exhibits the same behaviour (null pointer exception) at runtime, so I must have misunderstood your solution. Maybe I put the addedToWorld method in the wrong place? Thanks much for your help.
davmac davmac

2011/9/26

#
The signature for your addedToWorld method is wrong. You have:
1
2
3
4
protected void addedToWorld(WombatWorld theWorld)
{
    myWorld = theWorld;
}
Whereas it should be:
1
2
3
4
protected void addedToWorld(World theWorld)
{
    myWorld = (WombatWorld) world;
}
(I missed the typecast earlier - it is necessary of course because you are assigning a World expression to a WombatWorld variable). Because the method is not defined correctly, it doesn't override the method from the Actor class.
You need to login to post a reply.