Java Classes, Inheritance, and Interfaces Introduction Classes are a foundational element in Java. Everything in Java is contained in a class. Classes are used to create Objects which contain the functionality of the program. The basic concept behind classes is that a Class is like a cookie-cutter which can be used to stamp out objects. Building a Java program consists of creating Classes, relationships between Classes, and with these classes, creating Objects. Another way to think about Classes is that Classes have an External structure (or shape) and an Internal structure. Classes present a Public view to other classes and objects and have an internal structure which is how the class actually works. The external structure can be connected to the internal structure in various ways. Classes and Objects A class is a programming structure which consists of Properties and Methods. A Property is a data items (which can be a basic data type such as a number, character, string, Boolean, etc) or which can be an object defined by another class. A Method is a function. Both the Properties and the Methods makeup the Internal and External structure of a class. In Java classes are defined using the class statement: class Monster { private String name; private int health; private int power; private double gold; private boolean hasweapon; private int[] weapons; public Monster() { name = "Monster"; health = 100; power = 100; gold = 0.0; hasweapon = false; In this case, we have a class named Monster that has a set of Properties (the variables declared under the class). This class also has a constructor named Monster(), which is the name of the class. This constructor sets the default values for the properties. When creating a class you will typically include the following elements: A. Properties which are declared as private B. One or more Constructor methods which will be automatically called when an object of this class is created. C. Accessor and Mutator methods which are used to get and set the properties. D. Overloaded methods for equals and hashcode. Once you have a class, you can create Objects using the class name. If the class has a defined Constructor method then the method is called when the object is created. For example, if you had the Monster class you would use it to create various Monster objects: Monster golom1 = new Monster(); Monster collmonster[] = new Monster[10]; collmonster[0] = new Monster(); collmonster[1] = new Monster(); In this example, the Monster class is used to create an object named golom1 and used to create an array of Monsters.
Basically, the Monster class can be used just like any other data type such as int or double. The list of items you should create when you create a class includes constructor, accessor, mutator, equals, and hashcode methods. Since these are so commonly done, Eclipse can be used to automatically create these methods for you once you have created a class. 1. Start Eclipse. 2. Create a new Java project named GameCharacters. 3. Right click this project and choose New Class. 4. For the Package Name use GameCharactes and for the Class name use Monster. Click Finish when done. 5. Inside the Monster class enter the following Properties: private String name; private int idnumber; private int health; private int power; private double gold; private boolean hasweapon; private int[] weapons; The values for this class include the name of the monster, an idnumber which will uniquely identify the monster, and values for health, power, gold, and weapons status. It also includes an array which can hold weapon id values.
6. Right click inside the class (between the { symbols) and choose Source. You see the code Source options: The options on this menu allow you to quickly create methods for your class. The options include: E. Generate Getters and Setters this will create methods to get and set properties. F. Generate hashcode() and equals() this will create methods that override the hashcode method and the equals method. G. Generate tostring() this will create a method to override the tostring() class. H. Generate Constructor using Fields this allows you to create a constructor method using some of the fields in your class if you want to initialize the class with values. Properties can be read and write or read-only. A read-only property must be set through the Constructor and have a getter method but cannot be changed. The terms getters and setters refer to simple methods that allow the internal class properties to be set with a value (setters) and to retrieve values (getters). All properties will be set to private so that any access must be done through methods. This protects the internal values of the class. If objects created from this class will have an identity value so we can tell objects apart, then we need to override the hashcode() and equals() methods. The identity value must be able to uniquely identify the object. In this case, the idnumber field will be the identify field. We need to make this property read-only and to set the value through a constructor.
7. In the Source menu choose Generate Constructor using Fields. You see a dialog box listing all the properties in this class. You only want to choose the idnumber field. 8. Uncheck everything except the idnumber field and click the Generate constructor comments option and check the Omit call to default constructor super() field. 9. Click OK to generate the constructor. You will next create getters and setters for all properties. However, for the idnumber property you will only create a getter because this is a read-only property. 10. Right click in the class, choose Source, and choose Generate Getters and Setters.
11. Modify the dialog box so it looks like the figure. You will generate getters and setters for all properties but will only generate a getter for idnumber. You will also generate comments for these methods. 12. Click OK to generate the code. Finally, you will override the tostring method and the hashcode and equals methods. The tostring method is a utility method which, when called, returns a string id value of your object. This can be used for log files, debugging, etc. One way to create this method is by converting all the class properties into string values. 13. Right click in the class, choose Source, and choose Generate tostring() method. You see the tostring options:
14. Click OK to accept the default values. You will next generate the hashcode and equals methods. These are using when comparing objects or when you use the Java collection classes to manage objects. Typically, you want to make sure that each object has a unique ID value (in this case it will be the idnumber property). 15. Right click in the class, choose Source, and choose Generate hashcode and equals. You see the dialog box for generating hashcode and equals. You will use the name field and the idnumber field to generate a unique ID. 16. Unselect everything except the name and idnumber fields. 17. Make sure Generate method comments is selected and then click OK. You see the methods overriding hashcode and equals. The equals method will return true or false if two objects are the same and the hashcode method
will be used by collection classes to identify the object. For example, suppose we create the equals() method and then create two objects of type Monster: Monster a = new Monster(12345); a.setname( Frank ); Monster b = new Monster(87899); b.setname( Joe ); if( a.equals(b) ) System.out.println( Same Monster ); else System.out.println( Not the same Monster ); Lets fill out some more code for our monster class. These methods refer to a GameCharacter class which does not yet exist. 18. Click inside the class and enter the following lines of code: // Monster actions public GameCharacter fight(gamecharacter c) { c.sethealth( c.gethealth()-this.power); return c; public boolean areyoudead() { if(this.health<=0) return true; else Inheritance The idea behind inheritance is that many classes are variations on other classes and this fact should be used to simplify and make more efficient class design. The idea of inheritance is that a new class can be created by extending an existing class, keeping all the methods that will be used in the new class, and adding the unique methods for the new class. In order to better discuss inheritance it is useful to use some common terminology. A Base class, which is also called a Parent class, is the class which will be used as the basis of the derived class (also called the Child class). Base Class inherit from Derived class Parent Class inherit from Child Class Some of the rules in inheritance are defined by how the properties and methods in the base class are set: Access Levels Modifier Class Package Subclass World public Y Y Y Y protected Y Y Y N
no modifier Y Y N N private Y N N N For example, from within the same class anything with these four modifiers is accessible. However, a derived class cannot access private and no modifier options and only public and protected. There are a number of ways that you can implement inheritance from a Base class. These include: A. Add new methods to the Derived class while reusing all the public/protected methods from the Base class. B. The Derived class overrides a public/protected method from the base class C. The Base class includes one or more abstract methods which require the Derived class to override these methods and prevent the Base class from being used to create objects. In method A the base and derived classes can be used to create objects. The Derived class is just a special case of the Base class and includes its own special methods. For example, suppose we want to create a new Monster class called a BossMonster. This will have all the methods and properties of the Base class Monster but will have a new ability named Magic in which the monster can throw magic spells at the player s character. Since this is a new property the derived class needs to add the property, add getters and setters for the property, and add a method that is used to cast a spell on another game character. 1. Make sure your Monster class has been saved (there will be an error because the GameCharacter class has not been created). 2. Right click your Project and choose New and choose Class. You will let Eclipse handle setting up the new class. 3. In the New Class dialog box, for the Name enter BossMonster. 4. For the Superclass name type Monster. This is the Base class we wish to inherit from. 5. Click the check boxes for Generate Comments and for Constructors for superclass. 6. Click Finish. You see your class has been created and the constructor for the super class automatically added. public class BossMonster extends Monster { * @param idnumber public BossMonster(int idnumber) { super(idnumber); // TODO Auto-generated constructor stub The extends word indicates that this class is extended from the base class. Objects of type BossMonster have access to all the public methods and properties of the base class. For example: BossMonster m = new BossMonster(1234); m.sethealth(100); int x = m.gethealth();
You next want to add the Magic property which will represent a number of magical elements that can be used in battle. 7. Edit your class so it looks like: public class BossMonster extends Monster { private int MagicForce; * @param idnumber public BossMonster(int idnumber) { super(idnumber); // TODO Auto-generated constructor stub We will next let Eclipse create the getter and setter: 8. Right click in this class, choose Source, and select Generate Getters and Setters. 9. Click the MagicForce element and then click OK. The getters and setters are now created. All of the other public methods in the base class are still available to BossMonster objects. Another way to use inheritance is to override methods. A Derived class automatically gets access to all public/protected methods from the Base class. However, there are times when you want to extend one of the Base class methods. In this case the base class method: public boolean areyoudead() { if(this.health<=0) return true; else returns true if the health of the monster is gone. However, for BossMonsters both the health and the magic must both be zero. You want to override this method. 10. Right-click in the BossMonster class and choose Source. 11. Choose Overide/Implement methods. This brings up a dialog box that shows all the methods in the base class. 12. Choose the areyoudead() method and click OK. You see the code added to your class. @Override public boolean areyoudead() { // TODO Auto-generated method stub return super.areyoudead();
The metacharacter @Override is not a Java command but used to identify overridden methods. Notice that all the default method does is return the results of the Base class method areyoudead(). What we want to do is add in a check to see if the MagicForce value is also <= zero. This can be done by using an inline IF statement and combining this with the super.areyoudead() method (which returns a Boolean). 13. Edit this code so it looks like: public boolean areyoudead() { // TODO Auto-generated method stub return (super.areyoudead()&&(this.getmagicforce()<=0?true:false)); Look at this statement. The code: (this.getmagicforce() <=0? true: false) will call the getter and get the magic force value, compare it to zero, and if it is less than or equal to zero will return true, else will return false. The call to the Base class method is: super.areyoudead() and this will return true if the health is gone and false if there is some health. Combining these two Boolean checks together using the && statement looks like: true && true gives true false && true gives false true && false gives false false && false gives false The && operator returns a Boolean value by taking the two conditions and performing a Boolean operation.
The two classes look like: package GameCharacters; import java.util.arrays; public class Monster { private String name; private int idnumber; private int health; private int power; private double gold; private boolean hasweapon; private int[] weapons; * @param idnumber public Monster(int idnumber) {this.idnumber = idnumber; * @return the name public String getname() {return name; * @return the idnumber public int getidnumber() {return idnumber; * @return the health public int gethealth() {return health; * @return the power public int getpower() {return power; * @return the gold public double getgold() {return gold; * @return the hasweapon public boolean ishasweapon() {return hasweapon; * @return the weapons public int[] getweapons() {return weapons; * @param name the name to set public void setname(string name) {this.name = name; * @param health the health to set public void sethealth(int health) {this.health = health; * @param power the power to set public void setpower(int power) {this.power = power; * @param gold the gold to set
public void setgold(double gold) {this.gold = gold; * @param hasweapon the hasweapon to set public void sethasweapon(boolean hasweapon) {this.hasweapon = hasweapon; * @param weapons the weapons to set public void setweapons(int[] weapons) {this.weapons = weapons; /* (non-javadoc) * @see java.lang.object#tostring() @Override public String tostring() { return "Monster [name=" + name + ", idnumber=" + idnumber + ", health=" + health + ", power=" + power + ", gold=" + gold + ", hasweapon=" + hasweapon + ", weapons=" + Arrays.toString(weapons) + "]"; /* (non-javadoc) * @see java.lang.object#hashcode() @Override public int hashcode() { final int prime = 31; int result = 1; result = prime * result + idnumber; result = prime * result + ((name == null)? 0 : name.hashcode()); return result; /* (non-javadoc) * @see java.lang.object#equals(java.lang.object) @Override public boolean equals(object obj) { if (this == obj) return true; if (obj == null) if (getclass()!= obj.getclass()) Monster other = (Monster) obj; if (idnumber!= other.idnumber) if (name == null) { if (other.name!= null) else if (!name.equals(other.name)) return true; // Monster actions public GameCharacter fight(gamecharacter c) { c.sethealth( c.gethealth()-this.power); return c; public boolean areyoudead() { if(this.health<=0) return true;
else * package GameCharacters; * @author dcraig * public class BossMonster extends Monster { private int MagicForce; * @param idnumber public BossMonster(int idnumber) { super(idnumber); // TODO Auto-generated constructor stub * @return the magicforce public int getmagicforce() { return MagicForce; * @param magicforce the magicforce to set public void setmagicforce(int magicforce) { MagicForce = magicforce; /* (non-javadoc) * @see GameCharacters.Monster#areYouDead() @Override public boolean areyoudead() { // TODO Auto-generated method stub return (super.areyoudead()&&(this.getmagicforce()<=0?true:false)); You will notice that Eclipse automatically adds the notation @Override before the class. This is a compile-time flag to tell the Java VM that this method overrides a method in the Base class. The other term, Overloading, is a bit different. If your method in the Derived class has different parameters or return type then you are Overload a base class method: Override same method signature as Base class but different implementation Overload different method signature from Base class and different implementation You also notice that the reserve term super is used to call methods from the base class.
The Inheritance relationship allows one class to be used as a pattern for another class, in this case the Monster class is used as a pattern for the BossMonster class. However, the Monster class can still be used to create objects. There are times when you only want a Base class used as a pattern but not have the ability to create base class objects. In this case you would declare the base class abstract which would prevent this class being used to create objects. public abstract class BaseMonster { by including the term abstract in the class declaration you are telling the compiler that this class cannot be used to create objects but it can still be used in inheritance relationships. public class Monster extends BaseMonster { All the methods defined in the base class are still implemented in the derived class. Using an abstract class to enforce consistency is useful, but there are often times when you want to make sure that all the classes inheriting from the Base class create a necessary set of methods. For example, suppose that all our varieties of Monsters must have a method for fighting, but that each monster fights in a different way. One type may fight with magic while another fights with hands. This fight() method must be defined for each monster. When inheriting from a base class, and to ensure that the method defined in the base class is overridden in the derived class, you can make the method abstract. public abstract class BaseMonster{ public abstract void Fight(); In this case both the class and the method must be declared with the abstract term. When a class inherits from this class it must override this abstract method and create its own method. public class Monster extends BaseMonster { public void Fight() { If the derived class does not implement the abstract method then the compiler flags an error. You can use override to create new methods with the same method signature as the base class, but this is no guarantee that the derived class will implement the method. By making the method Abstract you ensure that this method will be implemented.
For example, suppose we want all Monsters in the game to have the same basic functionality for power, health, name, and fighting.