简体   繁体   中英

A better way of returning different types in Java

public int attack(Bear bear)
{
    int newStamina=bear.getStamina() - 50;  
    bear.setStamina(newStamina);
    return bear.getStamina();
}

To extend on my fabulous Bear class, I've decided to implement an attack (!) method.

I have 2 instances of my bear object: Bear1 and Bear2.

In my head:

Bear1.attack(Bear2);

then my code gets Bear2 current stamina value and takes away 50 from it, assigning it to the newStamina variable.

Bear2 then gets passed this new stamina variable with the setStamina method.

I then return Bear2 's current stamina, after the brutal bear attack.

This works, sort of. But I imagine there's a far better way.

Anyhoo. What I would like to do is, after:

int newStamina=bear.getStamina() - 50;

is:

if(newStamina <= 0)
{
    // the bear is dead!
}

Now my method attack returns an int , because if the bear doesn't die, it still has HP and I would like to output this current HP to the console or where ever.

If the bear is out of stamina, then I need to return something that signifies this.

What would you do? I can't return false, and I'm not sure that would work anyway.

I've tried this - returning an object instead of an int.

public Bear attack(Bear bear)
{
        int newStamina=bear.getStamina() - 50;  
        bear.setStamina(newStamina);
        if(newStamina<=0)
        {
            bear.isDead=true;
        }
        return bear;
}

// in main
while(Bear2.isDead==false)
{
            Bear1.attack(Bear2);
            System.out.println(Bear2.getStamina());
}

if(Bear2.isDead)
{
    System.out.println(Bear2.getName() + " is dead :(");
}

that seems to work..! will be interested to see other solutions.

A good rule of thumb is only modify instance variables inside set methods . Doing this will keep your code more manageable.

/**
 * reduce this bears stamina by the given amount
 */
public void reduceStamina(int reduction) {
    setStamina(getStamina() - reduction);
}

public void isDead() {
    return getStamina() < 0;
}

public void attack(Bear otherBear) {
    otherBear.reduceStamina(50);
    if(otherBear.isDead()) {
        this.victoryDance();
    }
}

From an OOP point of view, I would separate the Object "Bear" with its attribute "stamina" from the Object "Fight", which holds two bears and handles the attack and "still alive". I published some examples to a quite similar question some weeks ago: help with changing arrays into individual variables in Java

Instead of int you could return an Integer . In case the bear is dead you could return null .

public Integer attack(Bear attackedBear){
    Integer resultingStamina;
    ...
    if(resultingStamina<=0){
        resultingStamina = null;
    }
    return null;
}

that may do the job for you :

public int attack(Bear bear)
    {
        int newStamina=bear.getStamina() - 50;  
        bear.setStamina(newStamina);
        if(newStamina<=0)
        {
          bear.isDead=true;
        }
        return bear
    }

and in your main you verify if the returned bear still has stamina if not GAME OVER ...

public static void main()
{    
      Bear b1 = new bear();
      Bear b2 = new bear();
      while(!b2.IsDead())
      {
            b1.attack(b2);
            System.out.println(b2.getStamina());
      }

      System.out.println(b2.getName() + " is dead :(");
}



public class Bear
{
    private int _stamina;

    public int getStamina()
    {
          return _stamina;
    }

    public bool Isdead()
    {
          return _stamina == 0;
    }

    public void sufferAttack(int dommage)
    {
      _stamina = dommage > _stamina ? 0:(_stamina - dommage);
    }

    public void attack(Bear b)
    {
         b.sufferAttack(50);
    }
}

Now the reason.

First of all. Never expose internals attributes.Following the Demeters law, Nothing but the object itself should be able to change his current state.

Second, It make no sense to return an int(the stamina of the b2). B1 attack b2 and it a b1's method that return b2 stamina ? No. B1 have the responsibility to attack b1 and b2 the responsibility to suffer the attack and to provide a way to expose his current state.

You have to think about the responsibility of every class (and every method) before returning any kind of value.

When a bear attack I expect another bear to suffer an attack and when a bear suffer an attack I expect it to loose some stamina.

Something like this:

return new Pair <Integer, Boolean> (newStamina, bear.isAlive());

Not so good: return 2 ints, one representing the bool:

return new int [] {newStamina, bear.isAlive() ? 1 : 0};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM