© Doug Winnie 2021
D. WinnieEssential Java for AP CompScihttps://doi.org/10.1007/978-1-4842-6183-5_56

56. I Don’t Collect Those; Too Abstract

Doug Winnie1  
(1)
Mission Hills, KS, USA
 

When you play a role-playing game, you work together as a team with other people. This could be with other players in the same room in real life or simulated characters in a computer game. A party is a collection, a group of people who have something in common.

In Java, we can create collections using arrays or ArrayLists. These collections can be of everything, and we can use them to create collections of things that we define ourselves using classes. Java collections aren’t limited to things that are just in the core language—they can be instances of objects that we create in our own custom classes.

Here is an example, in our program, we can create a collection of characters in our game, called party:
import java.util.ArrayList;
public class Main {
    public static ArrayList party;
    public static void main(String[] args) {
        party = new ArrayList();
        party.add(new Mage("Jaana"));
        party.add(new Mage("Antos"));
    }
}

In this example, we now have a collection called party, and it contains two instances of the Mage class . Party on! Well—not quite.

When we create an ArrayList without generics, we are typing the collection to Object, meaning that anything can be added to it, including a number, string, or any object in Java. It also means that we can’t access the unique methods that are part of the Mage class, like showStats() . So if we try to add this line:
party.get(0).showStats();

we get an error, because it can’t find that method in the class that defines the collection: the Object class.

But, we can fix this. Using generics, we can type the ArrayList collection to the Mage type, then we can access the methods of Mage. We can update our code to read like this:
import java.util.ArrayList;
public class Main {
    public static ArrayList<Mage> party;
    public static void main(String[] args) {
        party = new ArrayList<Mage>();
        party.add(new Mage("Jaana"));
        party.add(new Mage("Antos"));
    }
}
Now we can use the methods that are part of the Mage class , and we can even use a for...each loop to go through each of the objects in the collection:
import java.util.ArrayList;
public class Main {
    public static ArrayList<Mage> party;
    public static void main(String[] args) {
        party = new ArrayList<Mage>();
        party.add(new Mage("Jaana"));
        party.add(new Mage("Antos"));
        for (Mage pc : party)
            pc.showStats();
    }
}
When I run this, I can get the output for each of the two Mage class instances that are now in the collection:
A new player character has been created!
A new mage named Jaana has been created!
A new player character has been created!
A new mage named Antos has been created!
Here are the stats for, Jaana
----------------------------------
Jaana, a mage:
    Strength: 13
Intelligence: 21
     Agility: 10
      Wisdom: 14
  Hit Points: 13 / 13
        Mana: 49 / 49
Here are the stats for, Antos
----------------------------------
Antos, a mage:
    Strength: 9
Intelligence: 20
     Agility: 13
      Wisdom: 15
  Hit Points: 9 / 9
        Mana: 50 / 50
Process finished with exit code 0
But we still have a problem. What about other classes? If I want to create a Fighter and add them to the collection, I can’t:
party.add(new Fighter("Sentri"));

The following code gives me an error, because the ArrayList collection is specifically typed to a Mage. So how do we fix this?

We need to think back to how we built the Mage and Fighter and other potential classes. We built them to extend the PlayerCharacter class , so, with that in mind, what are Mage and Fighter? They are PlayerCharacters! We can use the superclass as a tool to type any collection or object to accept any of the subclasses that extend it. We will also need to update our for...each loop, because it will need to look for PlayerCharacters in the collection, not a unique class like the Mage class:
import java.util.ArrayList;
public class Main {
    public static ArrayList<PlayerCharacter> party;
    public static void main(String[] args) {
        party = new ArrayList<PlayerCharacter>();
        party.add(new Mage("Jaana"));
        party.add(new Mage("Antos"));
        party.add(new Fighter("Sentri"));
        for (PlayerCharacter pc : party)
            pc.showStats();
    }
}

Now we can support multiple character types in our collection by typing it to the superclass. The collection can now hold the Mage and Fighter instances because they extend the PlayerCharacter superclass.

There is one important thing to note though. The showStats() method that we access in the for...each loop works, because it is located in the superclass. If we didn’t have that method in PlayerCharacter, we wouldn’t be able to use it, so if you know that you will have subclasses that have a method and will need to type collections and objects to a superclass, it is helpful to create empty methods so you can work with them.

But, we have one more issue. The collection can now support any class that extends PlayerCharacter—but that includes the PlayerCharacter class itself. We have designed PlayerCharacter to serve as a foundation to build our Mage, Fighter, and other classes from. We don’t want to be able to create instances of PlayerCharacter:
import java.util.ArrayList;
public class Main {
    public static ArrayList<PlayerCharacter> party;
    public static void main(String[] args) {
        party = new ArrayList<PlayerCharacter>();
        party.add(new Mage("Jaana"));
        party.add(new Mage("Antos"));
        party.add(new Fighter("Sentri"));
        party.add(new PlayerCharacter());
        for (PlayerCharacter pc : party)
            pc.showStats();
    }
}
In this example, we can create an instance of PlayerCharacter, which we never intended, and as a result, we get some strange output at the end when we run our program:
A new player character has been created!
A new mage named Jaana has been created!
A new player character has been created!
A new mage named Antos has been created!
A new player character has been created!
A new fighter named Sentri has been created!
A new player character has been created!
Here are the stats for, Jaana
----------------------------------
Jaana, a mage:
    Strength: 12
Intelligence: 17
     Agility: 10
      Wisdom: 12
  Hit Points: 12 / 12
        Mana: 41 / 41
Here are the stats for, Antos
----------------------------------
Antos, a mage:
    Strength: 9
Intelligence: 16
     Agility: 13
      Wisdom: 12
  Hit Points: 9 / 9
        Mana: 40 / 40
----------------------------------
Sentri, a fighter:
    Strength: 18
Intelligence: 9
     Agility: 9
Constitution: 12
  Hit Points: 60 / 60
        Mana: 0 / 0
Here are the stats for, null
Process finished with exit code 0
We need to find a way to have the PlayerCharacter class , but prevent our program from allowing us to create instances of it. The answer is to make it an abstract class. The abstract clause is added to the first line of a class definition:
public abstract class PlayerCharacter {
    // Name
    public String name;
    // Skill attributes
    public int strength;
    public int intelligence;
    public int agility;
    // Health and magic
    public int maxHitPoints;
    public int hitPoints;
    public int maxMana;
    public int mana;
    PlayerCharacter() {
        System.out.println("A new player character has been created!");
    }
    public void showStats() {
        System.out.println("Here are the stats for, " + name);
    }
}
With the class now defined as abstract, we can extend it to build subclasses, but we can’t create instances of it on its own:
party.add(new PlayerCharacter());

So this line of code now generates an error, stating that it is abstract, and can’t be instantiated. We still can type collections and other objects to it though—which is perfectly legal—because we aren’t creating new instances of the PlayerCharacter class; we are simply allowing its subclasses to work with it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.117.109