Java Lab Manual

Purpose

The use of inheritance to promote code reuse and

To prepare for this lab

  • Read Wu: Chapter 13 pages
  • Read through this laboratory session
  • Using your memory device, create a directory called lab13 and copy the four file .

To Complete this lab

  • This is an individual lab. You may ask the lab tutor for help and you may consult with your neighbor if you are having difficulties.
  • In this lab, you will complete Pets1.java and create two new files, Pets2.java and Pets3.java
  • When you have completed the lab, hand in copies of all three files, each of which contains the results of one run of the program.

13.1 Fundamentals of Inheritance - Part 1

Program:Open Pets1.java

Object-oriented programming languages such as Java provide a mechanism, called inheritance, to describe new classes in terms of existing ones The original class is called the base class, and a class that is built using the base class is called the derived class. Other terminology for the base class is parent class or super class. And, related terminology for the derived class is child class or sub class.

As an example, let's create classes such as Dog, Snake, and Poodle that can be used to keep track of information about a collection of pets. Since each pet has a name, each of these classes should have a data member String name and a getName method. This redundancy can be avoided by first defining a base class Pet from which the other classes are derived. The Pet class should define the data and methods that are common to all Pet objects. The non-private class members will be inherited by any class derived from the Pet class. The protected access modifier indicates that a class member is private to an outside class but is inherited by a sub class. Therefore, any class derived from the Pet class will inherit the instance variable protected String name and the method public String getName().

class Pet

{

protected String name;

public Pet()

{

name = "Unknown";

}

public Pet(String n)

{

name = n;

}

public String getName()

{

return name;

}

}

The inheritance relationship in Java is indicated by the reserved word extends. Therefore,

class Dog extends Pet

indicates that Pet is the base, or super, class and Dog is the derived, or sub, class.

class Dog extends Pet

{

public Dog(String s)

{

name = s;

}

}

Since a constructor must have a name that matches the class name, constructors are not inherited by the sub class. However, any constructor of a sub class must call, either implicitly or explicitly, a constructor of the super class. If the call to the constructor of the super class is implicit, the super class must have a constructor with no parameters, such as public Pet(). If the call to the constructor of the super class is explicit, the call must be the first statement in the body of the constructor of the sub class. The initial version of the Dog class contains the single constructor public Dog(String s), which contains a single statement that initializes the inherited instance variable name. Because it is implied, the call to Pet() does not appear.

Step 1: The Pet and Dog classes are defined in the program file Pets1.java along with the driver class Pets1. Predict the output of the program.

class Pets1

{

public static void main(String[] args)

{

Pet aPet = new Pet("George");

Dog aDog = new Dog("Spot");

System.out.println(aPet.getName());

System.out.println(aDog.getName());

}

}

______

______

Compile and execute the program Pets1.java. Correct you predicition if needed.

Step 2: Comment out the entire constructor public Pet() in class Pet. Record the compiler error message.

______

______

______

As previously stated, if the constructor in the sub class does not explicitly call a constructor from the super class, it will implicitly call the super class constructor with no parameters. When this constructor is omitted, the Dog class does not compile. To correct,uncomment the constructor. It is generally a good idea to include a default constructor in all of your utility classes to avoid this problem.

The constructor in the Dog class can explicitly call the constructor in the Pet class that initializes the instance variable name. The sub class always refers to its super class with the name super.

Step 3: Modify the constructor in the Dog class to explicitly call the constructor

public Pet(String n)in the super class. Replace

name = s;

with

super(s);

When s is passed to super, the constructor public Pet(String n) is called and s is assigned to n, which is then assigned to name. Compile and execute the revised program. Record the results.

______

______

Step 4:Now, let's add more methods to the Pet class. These will be methods that describe behaviors common to all classes that will be derived from Pet. Since all pets can move and speak, we will add move() and speak() methods to the Pet class. Also, all classes should have a toString (). Add these methods to the Pet class:

public String move()

{

return "run";

}

returns the String "run" since many pets, but not all, can run.

public String speak()

{

return "";

}

returns the empty String "" since there is no generic way for a pet to speak.

public String toString()

{

return "My pet " + name;

}

Compile the file.

Step 5: Now make changes to the Dog class. A sub class may define additional data members, which are unknown in the super class. In the class Dog, define an instance variable

protected int weight;

that is modified by protected so that subclasses of Dogwill inherit weight. Now, modify the Dog constructor to have a second parameter that initializes weight.

Compile the file.

Step 6: There are four ways to define methods in a sub class.

1. Define methods in the sub class with no connection to the super class.

A. Add an accessor method that returns the weight

2. Overwrite the inherited method.

B. Overwrite the speak method to return "Woof Woof"

3. Overwrite the inherited method, but call the inherited method

C. Overwrite the inherited toString method, but call the super class toString method. To do this use

the statement:

return super.toString() + " is a dog and weighs "+ weight + " pounds";

4. Inherit a method as is.

D. Do not modify the move method.

Now uncomment the code in the main method that tests the modified classes.

Pet myPet = new Pet("George");

Dog myDog = new Dog("Spot", 15);

System.out.println(

"\n" + myPet.toString() +

"\n " + "Speak: " + myPet.speak() +

"\n " + myPet.move() + " " + myPet.getName() + " " + myPet.move());

System.out.println(

"\n" + myDog.toString() +

"\n Speak: " + myDog.speak() +

"\n Weighs: " + myDog.getWeight() + " pounds" +

"\n " + myDog.move() + " " + myDog.getName() + myDog.move() + "\n");

Compile the file Pets1.java and run the program. Record the results.

______

______

______

______

______

______

______

______

Step 7: Add another class, Snake, to the file Pets1.java that satisfies the following requirements.

  • The class Snake is a sub class of the class Pet
  • Snake has an additional instance variable int length
  • Constructor: public Snake(String s, int len) initializes the name and length
  • Methods:
  • public int getLength()
  • public String speak() returns "Hiss Hiss"
  • public String move() returns "slither"
  • public String toString() returns "My pet __ is a snake and is __ inches long"

Then , add statements to the main method that create a Snake object and test its methods. Record any difficulties.

______

______

______

______

______

Step 8: Add another class, Poodle, to the file Pets1.java that satisfies the following requirements.

  • The class Poodle is a sub class of the class Dog
  • Constructor: public Poodle(String n, int w) initializes the name and weight
  • Methods:
  • public String speak() returns "Yip Yip"
  • public String toString() returns "My pet __ is a poodle and weighs __ pounds"

Then , add statements to the main method that create a Poodle object and test its methods. Record any difficulties.

______

______

______

______

Step 9: Answer these questions about the Poodle class.

1. Which class is the super class of Poodle? ______

2. List all the methods that are inherited by the Poodle class. Also, identify the class in

which each method is defined.

______

______

______

______

______

13.2 Polymorphism and Inheritance

The inheritance relationship is called the "is a" relationship because we can say that "A Dog is a Pet", "A Snake is a Pet", "A Poodle is a Dog" and, we can also say "A Poodle is a Pet". The class hierarchy that has been defined can be illustrated using the diagram

Pet

|

| |

Dog Snake

|

Poodle

The word polymorphism means "many forms" and has two applications in object-oriented languages. The first, which we have already seen, are polymorphic methods, known as overloaded methods. The second is polymorphic references, which are reference that may refer to many forms (types) of objects. For example, the Pet reference myPet may refer to a Pet, Dog, Snake or Poodle object since each of these is aPet. Therefore, an array of type Pet[] is used to store Pet references that can refer to a Pet object or to any object whose class is derived from the class Pet.

Step 10: Comment out the previously executed statements in main and uncomment the following statements.

Pet[] myPets = new Pet[4];

myPets[0] = new Pet("George");

myPets[1] = new Dog("Spot", 50);

myPets[2] = new Poodle("Rocky", 16);

myPets[3] = new Snake("Bruno", 20);

for(int j = 0; j < myPets.length; j++)

{

System.out.println(myPets[j].toString());

}

Predict what will be printed. Compile and execute the program. If needed, correct your predictions.

______

______

______

______

The principle of polymorphism guarantees that the toString method that is executed depends on the data type of the object, not on the data type of the reference (Pet). When

System.out.println(myPets[1].toString())

is executed, the toString method that is invoked is from the Dog class. When

System.out.println(myPets[3].toString())

is executed, the toStringmethod that is invoked is from the Snake class.

Step 11:Modify the main method by adding thisfollowing code to the body of the for loop.

System.out.println("Speak: " + myPets[j].speak());

System.out.println(myPets[j].move() + " " + myPets[j].getName() + "\n");

Mentally predict what will be printed. Compile and execute the program.Record any comments.

______

______

______

______

______

Step 12: Modify the main method by adding the following code to the body of the for loop.

System.out.println(" Weight: " + myPets[j].getWeight());

Predict the error. Compile the program. Record and explain the error message.

______

______

______

______

Step 13: The Java operator instanceof determines whether its first operand, an Object, is an instance of its second operand, a data type. The expression

myPets[j] instanceof Dog

has a value of true or false.

Modify the for loop of the main method by replacing the statement added in Step 12with

if(myPets[j] instanceof Dog)

System.out.println(" Weight: " + myPets[j].getWeight());

Compile the code and record the error message.

______

______

______

The getWeightmethod is defined in the Dog class. Since the Pet class does not define a getWeight method that compiler finds an error. Therefore, even though the print statement is executed only if myPets[j] references a Dog object, the Pet reference myPets[j] must be cast to a Dog reference .

Change the print statement to

System.out.println(" Weight: " + (Dog)myPets[j].getWeight());

Compile the code and record the error message.

______

______

______

The dot operator . has higher precedence that a cast (type) . Therefore, another set of parentheses is needed. Make this modification.

System.out.println(" Weight: " + ((Dog)myPets[j]).getWeight());

Mentally predict what will be printed. Compile and execute the program. Record any comments

______

______

______

______

Answer this question: What is the value of myPets[2] instanceof Dog ? Explain.

______

______

______

______

______

The Object class

In Java, all classes that do not explicitly extend a class, implicitly extend the class Object that is defined in the java.lang package. Therefore, every class is a descendant of the Object class. Specifically, the definition of the Pet class which begins with

class Pet

implicitly states that the super class of Pet is the Object class. Stating this explicitly, the definition of the Pet class would begin with

class Pet extends Object

Among the methods that are inherited by all classes from Object are two methods that we have worked with, toString and equals. The equals method defined in the class Object returns true if the reference passed to the method ==this reference. This method should be overwritten to compare the state of the two objects whenever possible. The toString method returns a string representation of the object and is automatically invoked on an object whenever a string representation is needed. For example, in order to print an object, a String is needed. This is why these two statementsproduce the same output.

System.out.println(myPets[j].toString());

System.out.println(myPets[j]);

Add this code that uses the inherited equals method to the main method after and outside of the for loop.

Pet p = new Pet("George");

if (p.equals(myPets[0]))

System.out.println("Same pet");

else

System.out.println("Different pets");

p = myPets[0];

if (p.equals(myPets[0]))

System.out.println("Same pet");

else

System.out.println("Different pets");

Compile and execute the program. Explain the results.

______

______

______

______

______

Abstract classes and Interfaces

Two other approaches to defining the Pet hierarchy of classes are to make the Pet class an abstract class or to make Pet an interface.

Program: Save your file Pets1.java as Pets2.java

Make the following initial changes:

  • Change the name of the class : class Pets1 to class Pets2
  • You may "clean up" the main method. Keep only the portion that declares and fills the array and the associated for loop.

An abstract method is a method that has no body. To define an abstract method, use the Java reserved work abstract, followed by the method header, followed by a semi-colon. For example, the speak method of the Pet class could be written as an abstract method rather than a method that returns an empty String. An abstract class is a class that contains at least one abstract method and must be declared to be abstract. Objects cannot be created from an abstract class. Any class that extends an abstract class must define bodies for all abstract methods, or the sub class must also be declared to be abstract.

Step 1:Make the following modifications to the Pet class. Replace the entire speak method with the single statement that is the abstract method header

abstract public String speak();

And, declare the Pet class to be abstract by adding abstract to the class declaration

abstract class Pet

Compile the modified program and record the error message. Explain

______

______

Step 2:Modify the driver class by replacing the statement

myPets[0] = new Pet("George");

with the statement

myPets[0] = new Dog("George", 100);

Compile and execute the modified program. Record the results.

______

______

______

______

______

Program: Save your file Pets2.java as Pets3.java

Change the name of the class : class Pets2 to class Pets3

Step 3: An interface can only define constant data members and abstract methods, which do not need the modifier abstract since they are abstract by default. Interfaces are not extended, rather they are implemented. Replace the entire Pet class with the Pet interface.

interface Pet

{

public String move();

public String speak();

public String toString();

}

The Pet interface cannot define the instance variable name and, therefore, should not list getName as a method in the interface.

Step 4: Make these changes to the Dog class.

1. Since Pet is no longer a class but, is an interface change the class header to

class Dog implements Pet

The super class of Dog is now implicitly the class Object.

2. Define the instance variablename, which will be inherited by any classes derived from

Dog(Poodle). Also, define a getName method.

3. Define the move method

4. Modify the toString method since the super class is now Object.

Step 5: Where needed, make similar changes to the Snake class. Record the changes that you need to make.

______

______

______

______

______

Step 6: The interface Pet may be used as a data type. Therefore, the array of type Pet[] is still valid and may store references to objects of any class that implements the Pet interface or is derived from a class that implements the Pet interface.

Compile and execute the program. Record any problems that you had.

______

______

______

______

______

______

______

______

Step 7: Explain why it was not necessary to make any changes to the class Poodle.

______

______

______

______

______

M. Manyo, Marquette University page 13.1