Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
J A V A L A B M A N U A L LAB OBJECT ORIENTED PROGRAMMING IN JAVA 13 Inheritance & Polymorphism 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 http://www.mscs.mu.edu/~marian/Labs/lab13/Pets1.java . 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. M. MANYO, MARQUETTE UNIVERSITY PAGE 13.1 13.1 FUNDAMENTALS OF INHERITANCE - PART 1 P r o g r a m : Open Pets1.java Object-oriented programming languages such as Java provide a mechanism, called i nhe ri tan ce , 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 PAGE 13.2 M. MANYO, MARQUETTE UNIVERSITY J A V A L A B M A N U A L statement that initializes the inherited instance variable name. Because it is implied, the call to Pet() does not appear. S t e p 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. S t e p 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 . S t e p 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. ___________________________________________________________________________________________ ___________________________________________________________________________________________ S t e p 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: M. MANYO, MARQUETTE UNIVERSITY PAGE 13.3 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. S t e p 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 Dog will inherit weight. Now, modify the Dog constructor to have a second parameter that initializes weight . Compile the file. S t e p 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"); PAGE 13.4 M. MANYO, MARQUETTE UNIVERSITY J A V A L A B M A N U A L Compile the file Pets1.java and run the program. Record the results. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ S t e p 7 : Add another class, Snake, to the file Pets1.java that satisfies the following requirements. o o o o 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: o public int getLength() o public String speak() returns "Hiss Hiss" o public String move() returns "slither" o 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. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ S t e p 8 : Add another class, Poodle, to the file Pets1.java that satisfies the following requirements. o o o The class Poodle is a sub class of the class Dog Constructor: public Poodle(String n, int w) initializes the name and weight Methods: o public String speak() returns "Yip Yip" o 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. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ M. MANYO, MARQUETTE UNIVERSITY PAGE 13.5 S t e p 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 | Poodle | Snake The word po lymo rph i sm 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 a Pet . 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. S t e p 1 0 : 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. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ PAGE 13.6 M. MANYO, MARQUETTE UNIVERSITY J A V A L A B M A N U A L 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 toString method that is invoked is from the Snake class. S t e p 1 1 : 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. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ S t e p 1 2 : 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. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ S t e p 1 3 : 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 12 with if(myPets[j] instanceof Dog) System.out.println(" Weight: " + myPets[j].getWeight()); Compile the code and record the error message. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________________________________________________________________________ The getWeight method 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 . M. MANYO, MARQUETTE UNIVERSITY PAGE 13.7 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 statements produce the same output. System.out.println(myPets[j].toString()); System.out.println(myPets[j]); PAGE 13.8 M. MANYO, MARQUETTE UNIVERSITY J A V A L A B M A N U A L 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. P r o g r a m : 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 a b str ac t me thod 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 a b str ac t c la ss 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. S t e p 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 ____________________________________________________________________________________ ____________________________________________________________________________________ M. MANYO, MARQUETTE UNIVERSITY PAGE 13.9 S t e p 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. ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ P r o g r a m : Save your file Pets2.java as Pets3.java Change the name of the class : class Pets2 to class Pets3 S t e p 3 : An i n terf ace 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 { public public public } Pet String move(); String speak(); String toString(); The Pet interface cannot define the instance variable name and, therefore, should not list getName as a method in the interface. S t e p 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 variable name, 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 . S t e p 5 : Where needed, make similar changes to the Snake class. Record the changes that you need to make. ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ PAGE 13.10 M. MANYO, MARQUETTE UNIVERSITY J A V A L A B M A N U A L ____________________________________________________________________________________ ____________________________________________________________________________________ S t e p 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. ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ S t e p 7 : Explain why it was not necessary to make any changes to the class Poodle . ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ ____________________________________________________________________________________ M. MANYO, MARQUETTE UNIVERSITY PAGE 13.11