简体   繁体   中英

Java: Referring to a Class inside its own method

I am working on an assignment that I'm trying to debug currently. I have numerous error: (method name) in class (SuperClass Name) cannot be applied to given types; . The project is repurposing a game centered around Procedural programming to the same game, but now around OOP. I'm new to Java and have been tasked with creating numerous Classes, two of which are subclasses to a Superclass (obviously), and I have been given what methods to have and their parameters. The problem I am having is that one method in a subclass is supposed to control a battle between two characters, the player and an enemy. Both of these classes are the subclass to the character class (superclass). Since this is a class assignment, I don't want to post everything that I have, but below is an example of the battle method I'm trying to perform. The problem I'm experiencing, and continue to have with " inheritance " in general, is exactly what is inherited between parent/child classes and how to pass certain values/variables between each of them.

In the example code below, this method is nested within the Player class that extends a Character class. This method needs to use and enemy from the Enemy class and perform the actions within. Depending on the outcome, I pass back a boolean to the main method of my program.

My problem is this; I'm unsure how to call a class that has been made " Player " class in this example, within a method that is already contained under the " Player " class. I was asked to use one argument for the method when called, Enemy . I'm positive that I'm not approaching this particular assignment in the appropriate way and there is a much better way to deal with this. But any help to understand what is possible is much appreciated as it will help me approach this assignment in the correct way.

Sample Method from the Player class is as follows:

public abstract class Character{ //Character Superclass - attack method called

public int attack(Player _player){
    Random randomNumbers = new Random();
    int enemyRandAtk = randomNumbers.nextInt(Weapon.getMaxDamage - Weapon.getMinDamage) + Weapon.getMinDamage;
    int enemyAtk = enemyRandAtk + getStrength();
    int charRemainingHP = _player.getHitPoints() - enemyAtk; //can I call _player in the Character class????
    System.out.printf("%s attacks with ATK = %d + %d = %d\n", getName(), getStrength(), enemyRandAtk, enemyAtk);
    System.out.printf("%s HP is now %d - %d = %d\n\n", _player.getName(), _player.getHitPoints(), enemyAtk, charRemainingHP);
    return charRemainingHP;
}

public class Player extends Character{


  public int attack(Enemy _enemy){
    Random randomNumbers = new Random();
    int enemyHP = _enemy.getHitPoints();
    int charRandAtk = randomNumbers.nextInt(Weapon.getMaxDamage - Weapon.getMinDamage) + Weapon.getMinDamage;
    int charAtk = charRandAtk + getStrength();
    int enemyRemainingHP = _enemy.getHitPoints() - charAtk;
    System.out.printf("\n\n%s attacks with ATK = %d + %d = %d\n", getName(), getStrength(), charRandAtk, charAtk);
    System.out.printf("%s HP is now %d - %d = %d\n\n", _enemy.getName(), enemyHP, charAtk, enemyRemainingHP);
    return enemyRemainingHP;
  }
  public boolean battleWizard(Enemy _enemy){
    Random randomNumbers = new Random();
    Scanner userInput = new Scanner(System.in);
    int spellCast = randomNumbers.nextInt(4) + 1;
    System.out.printf("*** %s vs The Evil Wizard ***\n\n", getName()); //getName() is in Player Class
    boolean charWinning = false;
    int updWizHP = _enemy.getHitPoints(); //****** Question 1. below
    do{
        System.out.print("Choose your action: \n" +
                         "1. Attack\n" +
                         "2. Attempt Spell Cast\n\n" +
                         "What would you like to do?: ");
        int battleDecision = userInput.nextInt();

        if (battleDecision == 1){
            updWizHP = Player.attack(_enemy); //**** Question #2 Below
            if (updWizHP <= 0){
                charWinning = true;
                break;
            }
        }else if(battleDecision == 2){
            System.out.print("Enter your guess: ");
            int playerGuess = userInput.nextInt();
            if (playerGuess == spellCast){
                System.out.printf("The %s's spell is cast successfully!  The Wizard's HP is now 0!\n\n", getName());
                charWinning = true;
                updWizHP = 0;
                break;
            }else{
            System.out.print("Your spell missed the Wizard.  Now he attacks!\n");
            }
        }
        if (getHitPoints() > 0){
            enemyDamage = Enemy.attack();
            decreaseHitPoints(_enemy.attack(Player)); \\**** Question #3 below
            if (getHitPoints() < 0){
                charWinning = false;
                break;
            }
        }
    }while(getHitPoints() > 0 && _enemy.getHitPoints() > 0);

    if (charWinning)
        return true;
    else
        return false;
   }
  }

Please keep in mind that this is a method within a subclass ( Player ) that holds roughly the same methods as ( Enemy ) short of this one and a few others.

In terms of my code above, here are my specific questions:

  1. Line 6 in method battleWizard (#1 Question in notes) - Since this method resides in the Player class, can I reference the Enemy class in this way? If not, what is a better way of doing so?

  2. Line 12 in method battleWizard (#2 Question in notes) - How can I reference a class that has an object created in it's own name when the method (code example) is in the class itself? I'd like to take the end-user's player player and reference that object within itself, if that makes sense? I am trying to visualize how the compiler will perform this task and can't imagine this ever working.

  3. 13 Lines from the bottom (#3 Question reference in notes): a) can you pass a method as a parameter to another method like this in Java? b) is the proper way to invoke another subclass (same subclass level as the one calling the class) like this or is it even possible?

Thank you for the help. As I mentioned before, since this is a class assignment I'd prefer not to provide more samples of my code. But inevitably, if it helps me to understand then I will. Please let me know what further information you need.

ETA: I added additional code to portray the relationship between the super and subclasses. For the Enemy subclass, it relies on the Character superclass for the attack method. So in my code example above, I hope that it clarifies 3.b. of my question. Any further information required, please let me know.

You are getting compilation errors because you defined attack(Player _player) which means you are allowing only Player objects to be passed but you are using like Player.attack(_enemy) which means passing Enemy object.

You need to correct this. Read my para, "As an aside...".

Line 6 in method battleWizard (#1 Question in notes) - Since this method resides in the Player class, can I reference the Enemy class in this way? If not, what is a better way of doing so?

As per your code sample, int updWizHP = _enemy.getHitPoints(); is a valid and sensible call if you want to get the hit points of the enemy. _enemy is your Enemy object and you can all any method on it as long as that method exists in that class.

Line 12 in method battleWizard (#2 Question in notes) - How can I reference a class that has an object created in it's own name when the method (code example) is in the class itself? I'd like to take the end-user's player player and reference that object within itself, if that makes sense? I am trying to visualize how the compiler will perform this task and can't imagine this ever working.

Since Player is extending Character , so you would have attack method inherited in Player class (visualize this is as defining attack method in Character class). So, you really don't need to use updWizHP = Player.attack(_enemy); but you can simply use updWizHP = attack(_enemy); . However, this is a compilation error, read my first and last portion of answer.

Now, since attack method is not using any instance field of Player class (state of the Player class) so you need not to worry but if it was then you had to think and decide that on which Player class object you want to call your attack method.

13 Lines from the bottom (#3 Question reference in notes): a) can you pass a method as a parameter to another method like this in Java? b) is the proper way to invoke another subclass (same subclass level as the one calling the class) like this or is it even possible?

  • For #3.a: Using decreaseHitPoints(_enemy.attack(Player)); you are not passing method to another method BUT first _enemy.attack(Player) will be evaluated and as your code an int would be returned and that value will be passed to decreaseHitPoints .
  • For #3.b: You are not invoking any sub-class but you are calling method on a object, it doesn't matter if the class that object represent lies in the inheritance tree or not. Only thing you need to make sure that it is a logical call and that method exists in the class. I guess _enemy.attack(Player) will give you compilation error because you are not defining Player as an object reference variable. You have to use some variable, cannot use class name like this. Better use _enemy.attack(this)


_enemy.attack(Player) this suggests that in attack method you want to pass an Player object, now either you use _enemy.attack(this) which means pass on current object on which battleWizard is getting called (make sense) or use _enemy.attack(new Player()) which means create a new object of Player class and pass that one.


As an aside , I think you better be defining public int attack(Player _player){ as public int attack(Character _character){ because like this in future you can use attack method to pass an Enemy object or some sub-class of Character

That's the beauty of "Inheritance" and "Program to interface" . I would recommend you to search and learn about these 2 concepts.


Few quick notes for you , may be you will be aware ( these are general notes trying to expose the topic/concept, there could be more limiting behavior, so please read more on each topic/concept ):

  • An object is a runtime representation of a class.
  • Methods of super class are inherited by sub-class, and to call them you need not to use an object, if you are calling from same class. Visualize this as defining that method in same class ( read more on inheritance in context public v/s protected v/s private methods ).
  • You can override the inherited methods.
  • A method accepting a super type can be invoked with object of any of its subclass. For example, in your case giveMeAnyCharacter(Character char) can be used as giveMeAnyCharacter(new Person()) or giveMeAnyCharacter(new Enemy()) .
  • In Java this means current object or instance and super means super class. So, either create a new object or if you want to use the same object on which you are presenting working then use this .
  • Always put your all common code (method or instance fields) in super class and let sub-classes take advantage of it using inheritance.

So, Java has "visibility" for methods and fields (and classes too), that defines what exactly is visible to an other class. Look up fe JLS 6.5.7.1-1, Simple Method Names and Visibility.

However, in your case "cannot be applied to given types" implies that you pass to a method different parameter types than what the signature says.

Still, for question 2, you just write this.attack(_enemy) , or simply attack(_enemy) . (BTW, what's with the underscores? I hope it's an artifact from the conversion and not something in your style guide)

Question 3: just use _enemy.attack(this) .

BTW, you have your OO terminology mixed up - one passes instances of classes around.

Your question is quite unclear, but I think the problem is your lack of terminology as well as a lack of understanding. I'll try a few pointers for you:

Line 6 in method battleWizard - Since this method resides in the Player class, can I reference the Enemy class in this way? If not, what is a better way of doing so?

int updWizHP = _enemy.getHitPoints(); //****** Question 1. below    

If getHitPoints() is in the Player class, you cannot call it with an Enemy instance . Fields and methods must exist in the classes of the instance being used in the call, or in their inheritance tree (super classes).

If getHitPoints() is both common to both Player and Enemy , you should place the method in the nearest class common to both - in your case, it would be the Character class. Putting the method in the Character class (and giving it protected or public visibility) allows it to exist in both Player and Enemy classes (and to be called using associated instances of Player and Enemy)

How can I reference a class that has an object created in it's own name when the method (code example) is in the class itself?

The only thing I can possibly imagine you describing here is the this keyword (which you don't seem to be using in your code). this represents the current instance of the class you are in.

So using this.attack(_enemy) is how you would get the current Player instance to attack the specified enemy.

a) can you pass a method as a parameter to another method like this in Java? b) is the proper way to invoke another subclass (same subclass level as the one calling the class) like this or is it even possible?

a) No. Java does not allow methods to be passed as parameters. If you want to pass a method, you must pass an instance (of a class containing the method) as a variable - say x - and then call the method you want to execute as x.method() . What you are doing is calling a method and using the return value as a parameter which is perfectly allowed.

decreaseHitPoints(_enemy.attack); // passing a method - not allowed
decreaseHitPoints(_enemy.attack(Player)); // passing a return value from calling a method - OK

b) I think what you want is this.decreaseHitPoints(_enemy.attack(this)); . Yes, you can (and should) call methods in other classes - but if your calling class is unrelated (ie not inherited from), you can only call those methods if they have been declared with public visibility.

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