Menios
Menios

Reputation: 145

Receiving an object derived from an abstract class as a parameter in method

I'm new to Java and I am currently learning about Abstract classes. Currently I am creating a simple RPG. Suppose I have an abstract class called Person, which extends to two other classes, Warrior and Wizard.

Now suppose that I have another abstract class called Weapon where from there we can create different types of weapons(swords, axes, bows etc..) which share some basic methods, that can be overwritten by other inherited classes, such as attack() or maintenance().

When a Person(Wizard or Warrior) will call the attack() method at some point in the game, I need to know who will be the attacker and who the defender (show I can modify their life bar status, durability of their weapons , etc) .

(Which essentially means, receiving two objects in the attack() method as parameters).

So here is where I am stuck. The combination of attacker-defender could be Wizard-Warrior, Wizard-Wizard, Warrior-Wizard or Warrior-Warrior.

How should I implement the attack() method in the Weapon class so it can permit me to receive an object as a parameter, without caring if the object is going to be wizard or warrior ? Could this be possible?

doing something like this for example?

void attack(Person attacker, Person defender)
{
    // add method logic here

}  

Thanks in advance.

Upvotes: 1

Views: 170

Answers (4)

Paul Richter
Paul Richter

Reputation: 11072

I'd like to propose a different alternative:

You have stated the attack method is on the Weapon class, however it seems the more logical place for this method would be in the Person class. If we think about it in concrete terms, it is not the weapon that is attacking the opponent, it is the Person, who is using the weapon, that is attacking.

It is difficult to give a concrete answer without seeing design of the game, however I will assume that your Person maintains a target field, pointing to whomever is being targeted by this Person object.

Additionally, when a player is attacked, they will no doubt "defend" themselves in some fashion (this could be simply in the form of mitigated damage due to armour, or some active ability or action, for example).

So your class will look something like this:

public abstract class Person {
    private Person target;
    private Weapon weapon;


    public void attack(){
        target.defend(calculateRawDamage());
    }

    private int calculateRawDamage(){
        // calculate weapon damage plus any modifiers, etc.
    }

    public void defend(int rawDamage){
        // calculate actual damage based on damage-mitigation modifiers
    }
}

This example makes a number of assumptions about how your game works, however as I said, it is simply an example, and hopefully illustrates a better way to implement game logic that does not reply on knowing the concrete Person or Weapon types, as each object will behave in their own specialized fashion according to their concrete type due to polymorphism.

Upvotes: 0

user3458
user3458

Reputation:

First step, derive Wizard and Warrior from Person (you may consider making Person an interface).

Second step, implement attack(Person attacker, Person defender) in terms of Person, not in terms of Warior or Wizard. All methohds common to Warrior and Wizard should be available to person. Any method not common should be made irrelevant to attack().

For example, if Wizard has castBestSpell(Person target) method, while Warrior has hitWithWeapon(Person target), you need to reduce both methods to Person.attack(Person target). Wizard and warrior will implement attack(Person target) differently: one by calling castBestSpell, one by calling hitWithWeapon.

Upvotes: 0

Steven Spasbo
Steven Spasbo

Reputation: 646

Not really answering the question, but why not move attack to the Person class, then you could write it out like

class Person
    public void attack(Person target, int damage) {
        target.setLife(life - damage);
        // or target.damage(damage), or however else you want to implement that
        ...
    }

then

myWarrior.attack(evilWizard, myWeapon.getDamage);

That just seems to make more sense to me, since the Person will be doing the attacking.

Upvotes: 2

Carlos Lopez
Carlos Lopez

Reputation: 94

it's easy, Wizard and Warrior need to extend Person

public class Warrior extends Person { }

It's easy.

Then you can check what it is...

if (attacker instanceof Warrior) for example.

Upvotes: 0

Related Questions