The generalization structure for this simple program is shown in Figure 1 below. Common to all characters in the game are the following attributes: (1) name, (2) strength, and (3) intelligence. Strength and intelligence are relative measures and have values in the range of 1 to 20. The higher the value, the stronger or more intelligent the character is.
Figure 1
As you can see in the provided Java code, class Game has specific member functions to add and remove Warrior and Wizard characters. You will test the existing code and your modifications to the code by using the class GameTest, which is a JUnit test class.
Note: We could use a Vector object to do this; it exploits the fact that all objects are a sub-type of the class Object. But instead you are required to implement this kind of functionality yourself and the Game class will become a specialized kind of container that manages objects which are kinds of game characters.
Note: You will test
your modifications with the class GameTest. When you modify the constructor the
the class Game
it is nessesary to modify the call to the constructor in the
method GameTest.setUp().
Modify your program to add the classes as shown in Figure 2. You should not have to change your new Game class to do this. All the classes should redefine member function whoAmI() (so that the information about characters is accurately given (for example, for class Druid, "I am a druid named... "). Note that Wizard no longer directly inherits from GameCharacter.
Again, modify the class GameTest to test your modifications and new classes. Some of the neccessary modifications are already indicated with comments in the source for GameTest, and an example test for the new class Centaur is given. Add similar tests for the classes Troll and Druid and modify the method GameTest.testWizardAttributes() to provide good tests for the new attributes of the class Wizard.
Note: You are doing OO design; ensure that you are using good priciples of encapsulation, interface abstraction, access controls, and documentation.
Java is unlike C++ in that it allows two different kinds of sub-typing relationships. We just looked at inheritance via the extendskeyword. Java also allows sub-typing by specifying that a class of objects will provide a certain specified interface. That is, classes of objects will behave in the same way if they implement the same interface (again a sub-typing relationship). We can specify a common interface much the same way we specify a class. The keyword interface is used in place of the keyword class in the definition. Method signatures and their return types are allowed to be specified for interfaces. Any state variables which are part of interfaces are static and final by default (i.e. they are constants that belong to the interface and are not part-of each object that implements the interface). We specify that a class will provide an interface by using the keyword implements. It is used in much the same way as extends. Since objects implementing the same interface are of the same "type/kind" polymorphism works across interface hierarchies in the same way it works across inheritance hierarchies. Only single-inheritance is allowed for class inheritance using extends, but multiple inheritance is allowed for interface inheritance using implements.
Create two interfaces called HumanCharacter and AnimalCharacter. Human characters should have a property called alignment which can have the value HumanCharacter.GOOD or HumanCharacter.EVIL. Animal characters should have a property called status which can have the value AnimalCharacter.FRIEND or AnimalCharacter.FOE. The interfaces should support get and set methods for reading/setting the alignment (status) value.
Warrior, Wizard, Druid shall be of type HumanCharacter, and Centaur and Troll shall be of type AnimalCharacter. Add a Werewolf character that is both an animal and a human character.
The whoAmI() methods of the characters should report there status and/or alignment and magical energy as appropriate.
When you have finished you modifications you will modify the JUnit GameTest class to test your modifications.
Question 1: For the original code given with the lab, specify whether each of the methods called by the class GameTest is: overloaded, over-ridden, polymorphic. Repeat this same exersize again for your completed modified code.
Question 2: The alignment and status state variables for the interfaces HumanCharacter and AnimalCharacter must be handled differently in implementation than the name, strength, etc. of a GameCharacter. Explain the difference. Why is there a difference?
Question 3: The access control for name, strength, etc. of a GameCharacter is friendly. Why is this a good choice in this case?
Question 4: Is it a good choice for the
attributes of the classes Warrior and Wizard to be private? What is the implication?
Question 5: This lab exersize is quite small. It can be
said that the interfaces (HumanCharacter
and AnimalCharacter) required
by the lab add complexity but do not help much. What might be some of
the benefits that they would provide as the software grows?
Question 6: How does polymorphism help you
write more compact and
abstract code?
Question 7: Produce a UML class
diagram for part 3. Show only the name of the classes in the class
icons and the relationships between the classes.