Java Reference
In-Depth Information
* roles.
* @param a role as defined in {@link Roles}
* @return {@code true} if the player has the
* role, and {@code false} otherwise.
*/
boolean hasRole(Roles role);
/**
* Add a role to the set of roles for which
* statistics are gathered by this player.
* Adding a role multiple times has no effect
* beyond the initial addition of the call. Roles
* cannot be removed once assigned to a
* player.
* @param role the {@link Role} to be
* added to the set of statistics for this
* player.
*/
void addRole(Roles role);
Supporting these changes in our implementation is pretty straightforward. We will keep fields
holding objects that support the
Batter
,
Fielder
, and
Catcher
interfaces. We will initialize
these as null objects, but when the role is added, we will allocate the object and start keeping
the statistics. There is a tricky bit in this because
Catcher
is a subtype of
Fielder
, but it's
nothing that we can't handle. While we are at it, we will also put a method that returns a ref-
erence to the
Player
object in each of the
Batter
,
Fielder
, and
Catcher
interfaces, and add
these methods to the corresponding implementation.
Of more interest to us here is how we keep track of the roles for a
Player
. We could keep a
series of
boolean
fields, but that seems excessive. We could build our own bit string, but that
would mean writing a lot of code.
Or we can look at the collections and see that there is a special
Set
that is made just for this
kind of thing. This is the
EnumSet
, which gives us
Set
semantics over an enumeration. It is a
parameterized collection, so we need to declare it as an
EnumSet<Roles>
, but doing that gives
us exactly what we want. Making all these changes gives us a
PlayerImpl
class that looks
like the following (eliding the methods that haven't changed):
package org.oreilly.javaGoodParts.examples.impl;
import java.io.FileInputStream;