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

2017/1/11

switch :: instanceof

ZoeF ZoeF

2017/1/11

#
Hello, I am wondering if it is possible to make a switch statement check if something is a instanceof something. For example i have this code wich i should be able to shrink if i would be able to do this.
private void checkAndCalc()
    {
        Map map = (Map) getWorld();
        Counter money = map.getMoney();
        int currentMoneyBalance = money.getValue();
        if(this instanceof Turret)
        {
            if(towerHelper.getPlace(validateTeller).equals("dot1.png"))
            {
                if(currentMoneyBalance >= COST_TURRET) 
                {
                    money.sub(COST_TURRET);
                    getWorld().addObject(new Base(Greenfoot.getRandomNumber(3)), getX(), getY());
                }
                else
                {
                    removeMe = true;
                }
            }
            else
            {
                removeMe = true;
            }
        }

        if(this instanceof Cannon)
        {
            if(towerHelper.getPlace(validateTeller).equals("blanck1.png"))
            {
                if(currentMoneyBalance >= COST_CANNON) 
                {
                    money.sub(COST_CANNON);
                    getWorld().addObject(new Base(Greenfoot.getRandomNumber(3)), getX(), getY());
                }
                else
                {
                    removeMe = true;
                }
            }
            else
            {
                removeMe = true;
            }
        }

        if(this instanceof Launcher)
        {
            if(towerHelper.getPlace(validateTeller).equals("blanck1.png"))
            {
                if(currentMoneyBalance >= COST_LAUNCHER) 
                {
                    money.sub(COST_LAUNCHER);
                    getWorld().addObject(new Base(Greenfoot.getRandomNumber(3)), getX(), getY());
                }
                else
                {
                    removeMe = true;
                }
            }
            else
            {
                removeMe = true;
            }
        }
Would it be possible to do something like this:
        int cost;
        String image;
        switch(this)
        {
            case Turret: 
                cost = COST_TURRET;
                image = "dot1.png";
            break;
            case Cannon:
                cost = COST_CANNON;
                image = "blanck1.png";
            break;
            case Launcher:
                cost = COST_LAUNCHER;
                image = "blanck1.png";
            break;
            case Boost:
                cost = COST_BOOST;
                image = "x1.png";
            break;
            default:
                cost = 0;
                image = "";
            break;
        }
Super_Hippo Super_Hippo

2017/1/11

#
I have no idea if it would be possible. I think that this code is in a class like "Tower" and the Turret/Cannon/... are sublasses of the "Tower" (or whatever). (Well actually, this couldn't work because the method is private...in this case, I don't know how you call that method in a different class... but still, let's say it would be that subclass thing described above.) I would do it like that: From each class you call that method, you pass a number. So in the Turret class, you use 'checkAndCalc(0);', in the Cannon class it is 'checkAndCalc(1)' and so on. Then you can use the switch:
protected void checkAndCalc(int type)
{
    int cost = 0;
    String image = "";
    switch(type)
    {
        case 0: //Turret
        cost = COST_TURRET;
        image = "dot1.png";
        break;
        
        case 1: //Cannon
        //... and so on
    }
}
davmac davmac

2017/1/11

#
Hmm...
if(this instanceof Turret)
You shouldn't generally need to check the type of "this" - you already know what type it is. If the code is in the Turret class, then the type is definitely Turret (or a subclass of Turret). The only reason why you would need code like what you have posted is if it is going into a base class of all the listed types. In that case, I believe you could do (untested code):
switch(this.getClass().getName()) {
    case "Turret": 
        cost = COST_TURRET;
        image = "dot1.png";
    break;
    case "Cannon":
        cost = COST_CANNON;
        image = "blanck1.png";
    break;
    // etc
}
However, you should not do this and should make use of polymorphism instead. That is, you should declare a (protected or public) "getCost" and "getImage" in the base class, and override them in the subclasses. Eg for Turret:
protected int getCost()
{
    return COST_TURRET;
}

protected String getImage()
{
    return "dot1.png";
}
and in Cannon you override them instead as:
protected int getCost()
{
    return COST_CANNON;
}

protected String getImage()
{
    return "blanck1.png";
}
... and so on. Then rather than the switch statement (in the base class), you just need:
cost = getCost();
image = getImage();
ZoeF ZoeF

2017/1/11

#
We did not learn protected yet and our instructor told us we should not use it for now. So if i would use this he would fail me :P Thats why i was trying to find a alternative. Tnx davmac for the this.getClass().getName() i presume this changes the Class name to a String value?
davmac davmac

2017/1/11

#
We did not learn protected yet and our instructor told us we should not use it for now.
You can use "public" instead of protected and it will work just as well. However, did you read the first part of my post above:
davmac wrote...
You shouldn't generally need to check the type of "this" - you already know what type it is. If the code is in the Turret class, then the type is definitely Turret (or a subclass of Turret)
and, importantly:
davmac wrote...
The only reason why you would need code like what you have posted is if it is going into a base class of all the listed types.
Is that the case? If it's not, you don't need any check of the type. Just put the appropriate code for each type in the code for the corresponding class.
Tnx davmac for the this.getClass().getName() i presume this changes the Class name to a String value?
Yes, it gives the name of the class a string.
danpost danpost

2017/1/11

#
As an alternative, you can place 'cost' and 'imageName' fields in the superclass with methods to return their values; and then, you only need to set the values from the subclasses:
// in superclass
private int cost;
private String imageName;

public int getCost()
{
    return cost;
}

public String getImageName()
{
    return imageName;
}

public void setCost(int value)
{
    cost = value;
}

public void setImageName(String name)
{
    imageName = name;
}

// in a subclass like Cannon
public Cannon()
{
    setCost(COST_CANNON);
    setImageName("blanck1.png");
    // etc.
This way the methods only have to be in the one class and you are not overriding the Actor class method 'getImage'; and 'cost' is just 'cost' and 'imageName' is just 'imageName' in the base class.
You need to login to post a reply.