You are on page 1of 90

MODULE 8: Classes and Inheritance

./ Overview . This module discusses inheritance. . Inheritance increases the flexibility in designing classes through the creation of general classes from which other classes can derive behaviors and attributes. The class that is at the top of a hierarchy of classes is known as the superclass. Classes that derive from this class are known as subclasses. All classes in Java derive from an ultimate superclass called Object. A subclass inherits all non-private data and methods of the superclass. Data and methods can be referenced as if they were declared as normal members of the class. A subclass does not inherit superclass constructors. A subclass can override the methods of the superclass. This module also discusses interfaces and polymorphism. An interface can only contain constants and abstract methods. A class can implement more than one interface, and unrelated classes can implement the same interface. If several classes implement a common interface, the methods declared as members of the interface can be executed polymorphically. Polymorphism provides a programmer with enormous flexibility. A method can be defined to accept a general class type or interface as an argument. Any class that extends from the general class or implements the interface can then be passed as an argument to the method.

Key terms . y Inheritance . y Abstraction . y Superclass . y Subclass . y Multiple inheritance . y extends . y Superclass object equals() and toString() methods . y Derived methods . y Overriding . y this and super y final y Interfaces y implements y Null method definition y Polymorphism y Dynamic binding or virtual method invocation

8.1. Inheritance and Object-Oriented Programming


.

8.1.1 Inheritance
. The technique of deriving new class definitions from an existing class definition is known as inheritance. Here are some reasons for using inheritance: -- Reuse of predefined, well-tested classes -- Standardization of behaviors across a group of classes -- Ability to use members of a family of classes interchangeably in methods With inheritance, the methods of the existing classes can be reused or changed. New attributes, fields, or data members, and methods can be added to adapt them to new situations. Inheritance defines "is a" relationships among classes and objects. Every object represents this "is a" relationship to its class. All objects inherit from the class that defines them. For example, in the code shown in Figure 1, the object referenced by f1 "is a" Fish. It inherits from the class Fish. .

In Figure 2, the object referenced by c1 "is a" Cat. It inherits its data and behavior from the class Cat.

The Fish and Cat classes define both common and different behaviors and data. The commonality of behaviors across some classes is the basis for inheritance. The programmer defining these classes could also define a class Animal that describes the data and behaviors common to the Fish and Cat classes. The inheritance model applied to these classes would be one where the Animal class is the parent class. The parent class would define common behaviors for the Fish and Cat classes. The Fish and Cat classes each inherit common behaviors from the parent class. The Fish and Cat classes also define their own adaptations of these behaviors, which include new data and new behaviors.

There exists an "is a" relationship between Animal, Fish, and Cat. A Fish is an Animal, and a Cat is an Animal. This "is a" relationship is the key concept of inheritance in object-oriented technology. Java allows "is a" relationships to exist between classes. The Java API defines all classes as inheriting from the class Object, which is at the ultimate root of all class hierarchies. When discussing class hierarchy, defining explicit inheritance from the Object class is not required. The Animal class automatically extends from Object. Since the Fish class extends from Animal, the Fish class has all the methods and attributes of the Object class. With inheritance the "is a" relationship extends to the root of the hierarchy. The object referenced by f1 "is a" Fish and "is an" Animal. The object referenced by c1 "is a" Cat and "is an" Animal. The Animal "is an" Object as shown in Figure 3. The "is a" relationship between Animal, Fish, and Cat can be thought of as is a plus additional functionality. Cat and Fish are examples of subclasses of the Animal class that provide additional functionality, such as the name attribute, getName() method and the play() method of the Cat class. Subclasses are classes that derive a core set of attributes and behaviors from another class. The class they derive from is referred to as the superclass. Another set of terms used to describe this relationship is that of a parent class, which is Animal, and child class, which is Cat or Fish. In Figure 3, the Animal class is the superclass for Cat and Fish, and the Object class is the superclass for Animal and all other Java classes.

Note that the UML does not repeat a description of all the attributes and methods derived from the superclass. When an attribute from a parent or super class will be modified, the UML will repeat this description. The UML will also describe any new behaviors or attributes that are added to the subclass. The # symbol is introduced in this UML. This symbol represents the access modifier protected. The protected access modifier allows all the subclasses and other classes in the same package to access the method or variable. In this example, the walk() and eat() methods are protected. This allows the subclasses access to these methods, but not classes in other packages.

8.1.2 Abstraction
.
The same Animal class can also be used to derive a Spider class. This new class does not have a name attribute like the Fish or Cat classes. However, all of these classes share some similar behaviors. This similarity of behaviors and attributes allows the programmer to define a class with these common behaviors and derive the subclasses Cat, Spider and Fish definitions from class Animal. This is shown in Figure 1. The Animal class generalizes the behaviors of many subclasses.

Often classes that define generalized behaviors such as the Animal class have little use as standalone classes. In any context, objects of the type Animal, a very general parent class, provide very little functionality. The Animal class could not provide the functionality needed for a Fish object or the functionality needed for a Cat object.

This class is an abstract representation of the classes that inherit from it. The placing of common behaviors in an abstract class is another design feature of inheritance. The Fish, Cat and Spider classes represent concrete classes from which a useful object can be created. Programmers arrive at abstract and concrete designs of classes in one of two ways. - The first way is generalization, or discovery of general behaviors among classes. - The second way is specialization, or the identification of specific adaptation of general behaviors or adoption of new behaviors in an inherited class. When designing classes, common fields and behaviors lead to generalizations about the classes. These generalizations can be implemented through the design of parent classes, which are also known as superclasses. Superclasses can then be designed to describe required and optional fields and behaviors. A superclass can be an abstract representation of common behaviors and data. When a superclass is an abstract representation, the superclass cannot be used to create any objects. Objects demonstrate behaviors of an abstract superclass through concrete implementations of these behaviors in subclasses. The Animal class can define common behaviors for Fish, Cat, and Spider objects. An object of the Animal class has almost no practical use. What a programmer uses is a specific instance of one of the derived classes. In object-oriented programming, the term concrete applies to a class from which an object can be created and used.

The term abstract is applied to classes from which no objects are expected to be created. In a program that manages data for an aquarium, the Fish class is derived as a concrete implementation of the Animal class. In a veterinarian application, the Cat object is a concrete implementation of the Animal class. In this manner, an abstract representation such as the Animal class can be used in two unrelated applications. This is shown in Figure 2. eneralizations of classes into a superclass can be either concrete or abstract. For example, an application can design classes to include an Employee class and two derived classes called Manager and Programmer. Scroll down the graphic in Figure 3 to see the details for the Manager and Programmer classes.

In this example, managers are represented using objects of the Manager class and programmers are represented using objects of the Programmer class. All other employees are represented using objects of the Employee class. All of the classes in the inheritance hierarchy are concrete classes. It is not unreasonable to expect to have objects of the type Employee without any additional information described in the class.

This is an example of a parent class and derived classes that are all concrete classes and can be used to create objects. This means that each class can be used to create objects of the class. In this model, an object referenced by e1 is an instance of the Employee class. An object referenced by m1 is a instance of the Manager class and contains attributes and methods of the Employee class. This object is a Manager and is an Employee. Similarly an object referenced by p1 is a Programmer and an Employee. While fish, cats, and spiders are all animals, their anatomy and behaviors are different. Fish swim and have fins instead of legs. Spiders have eight legs and cats only have four. These differences between fish, cats, and spiders represent specializations of the general and abstract class Animal. Fish, Cat, and Spider classes are subclasses of the parent superclass Animal. In the same sense, Manager and Programmer are subclasses of the parent class Employee. A subclass definition can include a method described in the parent class. The context in which this occurs is known as over-riding. This context suggests that the subclass version of a behavior is different than the parent class version of the behavior. Rules for overriding methods of a parent class are discussed in a later section. Some parent class methods must be overridden, in order to establish the subclass as a concrete class from which objects can be created. A parent class can hold general behaviors as in the example of the Animal class. However, in order to declare the class as an abstraction at least one method of the class must be defined as abstract and the class must be defined as abstract.

When a subclass derives from a parent class that has been declared abstract, the subclass must override all methods that are declared abstract in the superclass, or the subclass itself must be abstract. There are some important ideas regarding the abstract or concrete status of a class. - A superclass can be either abstract or concrete. - A subclass can also be abstract or concrete. - A subclass can be derived from an abstract parent class and continue to add new methods or attributes without overriding the parent class abstract methods. In this case, the subclass is also declared abstract and no objects can be created of this class. - In order to make the subclass concrete, all abstract methods of the parent class must be overridden.

8.1.3 The problem of multiple inheritance


In some object-oriented languages such as C++, a class can be derived from multiple parent classes or superclasses. In Java, a class may not have multiple superclasses. For example, if a Programmer object was both a member of the Person and Employee classes, and if both the Person and Employee classes have a field name and a method getName(), the JVM would not know which getName() method to use for a Programmer object. This is shown in Figure 1.

Figure 1

To avoid such confusion, and because Java is a strongly typed language, a class can only derive from one parent class.

A form of multiple inheritance is provided through the use of interfaces. These are described later in this module.

Inheritance hierarchies show the relationship between classes. It can show that the Programmer class is a subclass of the Employee class, which is a subclass of the Person class. In the same regards, it shows that the Person class is a superclass to the Employee class, the Programmer class, and all other classes that are subclasses of the Employee class or the Programmer class. Figure 2 illustrates the four level hierarchy path for the TextField class, which is used in a GUI.

Figure 2

GUIs include items such as windows and dialog boxes to facilitate user input. They are a vital aspect of virtually all applications. Figure 3 shows the API class documentation for a class.

Figure 3

Note that all API documentation presents the inheritance hierarchy for each class. Also notice that the class definition statement includes the declaration that the TextField class extends TextComponent. The keyword extends is used to declare an inheritance relationship between the classes. In Figure 4, the API documentation shows all the methods inherited from the parent class.

Figure 4

8.2 Java Language Support for Inheritance


8.2.1 Java language keywords in inheritance
The Java language includes specific keywords that support inheritance. The most important is the keyword extends. When a class extends from another class, it is considered a subclass. Extending from another class is also known as subclassing. The idea behind keyword extends is that the child class definition includes all of the non-private attributes and behaviors of the parent class and adds its own unique attributes and behaviors.

Another keyword used with inheritance is super, which allows programmers to access constructors and overridden methods of a parent class. Since Java does not permit multiple inheritances, there is only one parent class. The keyword super provides a reference to the derived attributes of the object. The keyword super cannot access private features or circumvent access rules.

Figure 1 highlights the Java keywords that are associated with inheritance.

8.2.2 Object class


The Java language provides comprehensive support for inheritance through the API of classes. Almost any Java program that creates and uses GUIs, uses inheritance models that are implemented in the classes that form the Abstract Window Toolkit (AWT) of classes. Windows is an example of a operating system that creates and uses GUIs. Each class that has been created extends from the Object class, which is the superclass of all classes. The table in Figure 1 shows all of the methods of the Object class.

Figure 1

All the attributes and behaviors of an object are defined by its class, its superclass, and the superclasses of the superclasses. Since the Object class is the superclass of all classes in Java, the attributes and behaviors defined in Object are present in all Java objects. As a result, Object class behaviors and attributes are inherited by all new classes.

The common Object ancestor of all classes allows the programmer to have a generic reference to any class, both API or user written. It is common for a methods to have an argument that states methodX(Object obj). This type of declaration suggests that the method will accept a reference to any type of object. Each class that is created includes all of the methods of the Object class. Although every class extends the Object class, this information never has to be declared in the class definition. It is assumed that the class Animal or Employee extends the class Object, and therefore does not have to be declared. Every class is a descendent of the Object class. When a custom class is created without extending from a parent class, the ava platform implicitly includes an extends java.lang.Object as part of the class definition. In this way, all classes extend from Object, either directly or indirectly through the hierarchy of the parent class. In the example of Animal, Cat and Fish, the Animal class derives directly from the Object class, and the Cat and Fish classes derive indirectly through their parent class, from the Object class. Some methods of the Object class require special consideration. These are:  the equals()method and  the toString() method. These methods perform very generic actions when executed.

For example, the equals() method will compare its reference value to that of another object. This is a comparison of the addresses of two objects and not the data. The toString() method will convert the reference value of an object to a String. Either of these methods may not be very useful when comparing or printing object data. In a later section the ways of overriding to change the operations of these methods will be explored. In Figure 2, all of the derived methods of the Programmer class from the parent class Employee are identified. Note that all the derived methods from the Object class are also identified.

8.3 Access Modifiers and Inheritance


.

8.3.1 Role of access modifiers in inheritance


.
Access modifiers control what superclass attributes and methods are inherited by the subclass. Figure 1 describes access modifiers and their impact on inheritance.

The modifiers of the parent determine if a subclass can directly access parent class variables and methods and override parent class methods. These are the implications of the use of different modifiers: ---> private - A subclass cannot access these variables and methods, thus the subclass cannot override these methods. No other class can access these either. ---> protected - A subclass can be created in the package that the parent class belongs to or in a different package. The protected modifier allows the subclass to access any protected attribute or method, and to override any protected method.

Additionally, classes in the same package as the parent class can access the protected method and attribute. Default access is when no access modifier is used. In this state, the parent class attributes can be accessed by subclasses in the same package. Although methods can be overridden in subclasses of the same or different packages, the attribute cannot be accessed by the subclass in a different package. Figure 2 shows the impact of inheritance when a subclass is in the same package as the parent class and when the subclass is in a different package.

It is important to understand that all methods and data from a parent class exist in the subclass object. However, the private attributes and methods are inaccessible to the subclass object. The code examples shown in Figure include three classes, which are the Parent class, the Child class, and a Test class. The Parent class:

The Child class:

-- A private attribute in the Parent class is not directly accessible to the subclass. -- The non-private method of the Parent class is directly accessible. -- The non-private method accesses the private attribute. This code shows that inaccessibility does not mean that the private methods and data do not exist.

Note that the Child class makes a call to the Parent class getX() method and the public variable Y directly. Both of these are part of the inherited properties from the Parent class. Review the code of the Test class 4.

Note that the Child object c is used to directly access the method getX() from the Parent class. Both of these examples show that all non-private attributes of a parent class are inherited and directly accessible.

If a subclass declares an attribute with the same name as an attribute of the superclass, a duplicate or shadow attribute is created. Avoid doing this unless it is an OO design requirement.

This introduces uncertainty into the behavior of the classes. If another programmer uses these classes and expects the values of attributes in the parent class but receives the values of the shadow variables in the child class, their code may not work properly. If a subclass declares a method with the same name, returntype, and argument as a parent class method, this is known as overriding.

!!!! If the parent class declares a method to be final, this


method cannot be overridden. !!!! If the parent class declares a method to be static this method cannot be overridden in the child class. When a child class overrides a parent class method, the child class can access the parent class method with the keyword super.

8.4
.

Overriding

8.4.1 Method overriding


.
While inheritance provides extensive support to reuse existing classes, many of the methods of a superclass may need customizing. For example, the Object class methods equals() and toString() have limited uses if they only compare or print the addresses of objects. A toString() method that prints the data of an object in a formatted manner or an equals() method that compares the values of two objects, would be more practical. The ability of a programmer to redefine or customize the definition of a parent class method is known as overriding. This is another component of inheritance. Almost any method that is inherited can be overridden. The exception is a non-private method that has been declared final in the parent class. Recall that access modifiers influence inheritance. Only methods that are accessible can be overridden. The table in Figure 1 describes the rules for overriding parent class methods.

In the Animal class example, all of the subclasses of animals implement the eat() method in different ways. Therefore, the eat method has been overridden in each of the subclasses. Both the Spider and Cat objects use the walk method defined in the Animal class, which describes how many legs are used to walk. Since Fish do not walk, a class which represent them does not need a walk method. This method can be overridden in the Fish class to reflect this situation. Figure 2 illustrates the Animal class methods that have been overridden in each of the subclasses.

8.4.2
.

Overriding of object class methods

In general, class designs should include overriding the equals(), hashCode(), and toString() methods. Apply this to the Student class used in previous examples. This is shown in Figure 1.

Output:

It may be necessary for a class to override the following Object methods. The equals/hashCode are listed together since they must be overridden together.

-----

clone equals/hashCode finalize toString

A class cannot override these Object methods, since they are final: -- getClass -- notify -- notifyAll -- wait The Student class has methods to access private data. The Student class inherits the equals() method and the toString() method from the Object class. Using these methods with Student objects produces information that is not useable. For example, both Student objects contain the same data. However, each Student object has a different address and causes the method to return false. The System.out.println() method will use the toString() method of an object to print information about the object. Since the toString() method in the Object class only returns the memory address of the object as a String, this is what is printed. To deal with these limitations, override the toString(), equals(), and the hashCode() methods in the Student class. The System.out class uses the toString() method of an object to print information about the object. The Student version of the toString() method will return a String that represents the student name, identification, and other information. When the System.out.println() method is provided a reference to the Student object, it uses

the overridden toString() method to print student information that is useful. This is shown in Figure 2.

Since two Student objects will need to be compared to ensure that none of the student information is duplicated, the equals() method is overridden. It is possible for two Student objects to have the same data, but since they are not the same object, they will have different memory addresses. The address of an object is calculated using a hashing algorithm, which is a unique identifier given to each object on the heap. The hashing algorithm is in the code of the hashCode() method and is used to generate a unique value known as the hashvalue for the object. To ensure that this unique identifier is the same, the hashCode() method of the object needs to be overridden.

In this example, the hashCode() method uses the student identification to determine a hashvalue. The method returns an integer as the hashvalue of the object. The equals() method is overridden to compare the data in the fields of the two objects. If all fields are equal, then the method returns a true. A test of the hashvalue of the objects is also included.

In Figure 3, the equals() method is overridden, but not the hashCode() method. Although the objects contain the same data, since each one has been assigned a different hashvalue they will be considered different objects. Figure 3:
4 * Student Class establishes the student id, name and grade 5 * @author Cisco Teacher 6 * @version 2002 7 */ 8 public class Student 9 { 10 private final String studentName; 11 private String grade; 12 private int studentID; 13 publicstatic final int courseNumber = 12345; 14 // null constructor 15 public Student( ) 16 { 17 studentName = ""; 18 } 19 // constructor with 2 arguments 20 /** 21 * @param name The student's name as a String 22 * @param grd The student's grade as a String 23 */ 24 public Student(String name, String grd) 25 { 26 studentName = name; 27 grade = grd; 28 studentID = 99999; 29 }

30 // constructor with 3 arguments 31 /** 32 * @param name The student's name as a String 33 * @param grd The student's grade as a String 34 * @param id The student's id as an int 35 */ 36 public Student(String name, String grd, int id) 37 { 38 studentName = name; 39 grade = grd; 40 studentID = id; 41 } 42 // Print student name and grade 43 public void printData() 44 { 45 System.out.println("Student name is: " + studentName + 46 " Grade is: " + grade); 47 } 48 // get student's name 49 /** 50 * @return The student's name as a String 51 */ 52 public String getStudentName() 53 { 54 return studentName; 55 } 56 // set student's grade 57 /** 58 * @param newGrade The student's new grade as a String 59 */ 60 public void setGrade(String newGrade) 61 { 62 grade = newGrade; 63 } 64 // get student's grade 65 /** 66 * @return The student's grade as a String 67 */ 68 public String getGrade() 69 { 70 return grade; 71 } 72 // set student's id 73 /** 74 * @param id The student's id as an int 75 */ 76 public void setStudentID(int id)

77 { 78 studentID = id; 79 } 80 // get student's id 81 /** 82 * @return The student's id as an int 83 */ 84 public int getStudentID() 85 { 86 return studentID; 87 } 88 // overridden toString method 89 public String toString() 90 { 91 return ("Student name is: " + studentName + 92 " ID is: " + studentID + 93 " Grade is: " + grade); 94 } 95 // overridden equals method 96 /** 97 * @param s A student as a Student data type 98 */ 99 public boolean equals(Student s) 100 { 101 boolean test = false; 102 if(s.studentName == studentName 103 && s.studentID == studentID 104 && s.grade == grade) 105 { 106 test = true; 107 } 108 return test; 109 } 110 // Main method 111 public static void main(String[] args) 112 { 113 Student s1, s2; 114 s1 = new Student("Mary Jane", "A"); 115 s2 = new Student("Mary Jane", "A"); 116 if(s1.equals(s2)) 117 { 118 System.out.println("The two students are the same!"); 119 } 120 System.out.println(s1); 121 System.out.println(s1); 122 } 123 \}// End of Student class 124 }

125

In Figure 4, the hashCode() and the equals() methods are both overridden. This yields a more accurate result of the comparison of the two objects.
4 * Student Class establishes the student id, name and grade 5 * @author Cisco Teacher 6 * @version 2002 7 */ 8 public class Student 9 { 10 private final String studentName; 11 private String grade; 12 private int studentID; 13 public static final int courseNumber = 12345; 14 // null constructor 15 public Student( ) 16 { 17 studentName = ""; 18 } 19 // constructor with 2 arguments 20 /** 21 * @param name The student's name as a String 22 * @param grd The student's grade as a String 23 */ 24 public Student(String name, String grd) 25 { 26 studentName = name; 27 grade = grd; 28 studentID = 99999; 29 } 30 // constructor with 3 arguments 31 /** 32 * @param name The student's name as a String 33 * @param grd The student's grade as a String 34 * @param id The student's id as an int 35 */ 36 public Student(String name, String grd, int id)

37 { 38 studentName = name; 39 grade = grd; 40 studentID = id; 41 } 42 // Print student name and grade 43 public void printData() 44 { 45 System.out.println("Student name is: " + studentName + 46 " Grade is: " + grade); 47 } 48 // get student's name 49 /** 50 * @return The student's name as a String 51 */ 52 public String getStudentName() 53 { 54 return studentName; 55 } 56 // set student's grade 57 /** 58 * @param newGrade The student's new grade as a String 59 */ 60 public void setGrade(String newGrade) 61 { 62 grade = newGrade; 63 } 64 // get student's grade 65 /** 66 * @return The student's grade as a String 67 */ 68 public String getGrade() 69 { 70 return grade; 71 } 72 // set student's id 73 /** 74 * @param id The student's id as an int 75 */ 76 public void setStudentID(int id) 77 { 78 studentID = id; 79 } 80 // get student's id 81 /** 82 * @return The student's id as an int 83 */

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

public int getStudentID() { return studentID; } // overridden toString method public String toString() { return ("Student name is: " + studentName + " ID is: " + studentID + " Grade is: " + grade); } // overridden equals method /** * @param s A student as a Student data type */ public boolean equals(Student s) { boolean test = false; if(s.studentName == studentName && s.studentID == studentID && s.grade == grade) { test = true; } return test; } //overridden hashCode method /** * @return The student's info as an int */

115 116 117 118 119 120 121 122 123 124 125 126 127

public int hashCode() { String temp = String.valueOf(studentID); return temp.hashCode(); } // Main method public static void main(String[] args) { Student s1, s2; s1 = new Student("Mary Jane", "A"); s2 = new Student("Mary Jane", "A"); if(s1.equals(s2)) {

128 same!"); 129 130 131

System.out.println("The two students are the } System.out.println(s1); System.out.println(s1);

132 } 133 \}// End of Student class 134 } 135

8.4.3
.

Overloading versus overriding

The figure presents a comparison of overloading and overriding techniques. Both can be used in classes that form an inheritance hierarchy.

8.5 Use of this and super


.

8.5.1 Access parent and subclass methods and data


. A subclass should be viewed as incorporating all the methods and attributes of its hierarchy of parents. The figure illustrates the subclass SportsCoupe and the parent class BaseModelAuto. To reference the methods and data of each object, it is possible to use the variables this and super in the methods. All of the methods of the subclass include the this variable and the super variable. The this variable contains a reference to the subclass object. The super variable contains a reference to the parent object. The use of super is not required for attributes and methods that have not been overridden by the subclass. In the sample code, this and super are used in two places. The parent class method is overridden in the subclass. The overridden method calls the parent class method using the super variable. The overloaded method uses the this variable to call the method of the parent class that is overridden in this subclass. To add more functionality to a parent class method, instead of completely overriding the method, call the overridden method using the super keyword. For example, the getAccessories method in the subclass SportsCoupe

added functionality to the getAccessories method in the superclass BaseModelAuto with the code on lines 15 through 18.

1 /** 2 * Java Program: SportsCoupe.java 3 * @author Cisco Teacher 4 * @version 2002 5 */ 6 public class SportsCoupe extends BaseModelAuto 7{ 8 protected String accessories = "Moon roof\n"; 9 10 //constructor 11 12 /** 13 * @return The car's accessories as a String 14 */ 15 public String getAccessories() //overridden method 16 { 17 return super.getAccessories() + accessories; 18 } 19 20 /** 21 * @param options The car's options as a String 22 * @return The car's accessories as a String 23 */ 24 public String getAccessories(String options) //overloaded method 25 { 26 return this.getAccessories() + options; 27 } 28 //additional methods 29 30 public static void main(String[] args) 31 { 32 SportsCoupe myCar = new SportsCoupe(); 33 System.out.println("\nList of options includes:\n" 34 + myCar.getAccessories()); 35 System.out.println("\nList of options includes:\n" 36 + myCar.getAccessories("Chromeplated Wheels")); 37 } 38 } // end of SportsCoupe class 39

1 /** 2 * Java Program: BaseModelAuto.java 3 * @author Cisco Teacher 4 * @version 2002 5 */ 6 public class BaseModelAuto 7{ 8 protected String accessories; 9 accessories = "Power Steering\nPower Windows\n"; 10 11 //constructor 12 13 /** 14 * @return The accessories as a String 15 */ 16 public String getAccessories() 17 { 18 return accessories; 19 } 20 21 //additional methods 22 } // end of BaseModelAuto class 23

8.6 Inheritance and Constructors


.

8.6.1 Handling constructors in inheritance


.

Inheritance makes non-private code and data defined in the parent class accessible to the subclass. The only exception is constructors. Constructors are not inherited in the normal way, even if they are non-private. Constructors must be defined for each subclass. Figure 1 shows the use of the new operator to construct an object and the matching constructor that is used.
1 /** * Java Program: MyClass.java 2 * @author Cisco Teacher 3 * @version 2002 4 */ 5 6 public class MyClass 7{ 8 private int studentID; 9 private int creditHoursEarned; 10 private double tuitionBalance; 11 private String studentName; 12 private String studentAddress; 13 14 //Overloaded Constructors, demonstrating "name mangling" 15 public MyClass() 16 { 17 } 18 19 /** 20 * @param id The student's id as an int 21 */

22 public MyClass(int id) 23 { 24 studentID = id; 25 } 26 27 /** 28 * @param id The student's id as an int 29 * @param credit The student's credits as an int 30 */ 31 public MyClass(int id, int credits) 32 { 33 studentID = id; 34 creditHoursEarned = credits; 35 } 36 37 /** 38 * @param id The student's id as an int 39 * @param balance The student's balance as a double 40 */ 41 public MyClass(int id, double balance) 42 { 43 studentID = id; 44 tuitionBalance = balance; 45 } 46 47 /** 48 * @param id The student's id as an int 49 * @param name The student's name as a String 50 */ 51 public MyClass(int id, String name) 52 { 53 studentID = id; 54 studentName = name; 55 } 56 57 /** 58 * @param id The student's id as an int 59 * @param address The student's address as a String 60 */ 61 // causes compilation error since MyClass constructor with (int, String) 62 // already defined 63 public MyClass(int id, String address) 64 { 65 studentID = id; 66 studentAddress = address; 67 }

68 69 /** 70 * @param address The student's address as a String 71 * @param id The student's id as an int 72 */ 73 // Could reverse arguments since (String, int) 74 // pattern has not been used 75 public MyClass(String address, int id) 76 { 77 studentID = id; 78 studentAddress = address; 79 } 80 81 /** 82 * @param id The student's id as an int 83 * @param name The student's name as a String 84 * @param balance The student's balance as a double 85 */ 86 public MyClass(int id, String name, double balance) 87 { 88 studentID = id; 89 studentName = name; 90 tuitionBalance = balance; 91 } 92 93 //Additional methods 94 95 public static void main(String[] args) 96 { 97 MyClass a = new MyClass(); 98 MyClass b = new MyClass(1234, 12); 99 MyClass c = new MyClass(1234, 1000.00); 100 MyClass d = new MyClass(1234, "Mary Smith"); 101 MyClass e = new MyClass("Phoenix, AZ", 1234); 103 MyClass f= new MyClass(1234, "Mary Smith", 1000.00); 103 } 104 } // end of MyClass class 105

In this example, the code for MyClass includes overloaded constructors. Overloading means different versions of the same method exist in the same class.

The keyword extends means that an object of the parent class is constructed and then extended to include the data and methods of the subclass. The creation of objects in an inheritance model is far more complex than the creation of objects with the Object parent class. This is shown in Figure 2.

When the inheritance model is applied to a class definition, a number of rules apply that affect the inclusion of constructors in the child class. In order to understand these rules, it is important to recognize that a child class object contains within it the attributes of its

parent classes, all the way up to the level of the Object class. When an object of the child class is created, all the attributes of its parent class are created first, and then the attributes of the child class. Recall the steps by which an object is created. When the new operator is invoked, memory is allocated to all the attributes of the object, and the default values are assigned. Explicit initialization occurs and then the code of the constructor is executed. After all the attributes of the subclass and parent class of the object have been initialized, then the constructors for each of the classes are executed. This always begins with the execution of the parent class constructor. Since the parent class attributes are created first, the corresponding constructor for this class is executed to complete the parent portion of the object. Since the first constructor call in the child class constructor is a call to the parent class constructor, a number of situations exist regarding the inclusion of constructors in the parent and child class: -- If the parent class uses the default constructor, then the child class can also use the default constructor. Recall that the default constructor is inserted by the compiler if none is provided. In the case of derived or subclasses, the compiler will insert a default constructor in the child class and it will also insert the statement super(), which is a call to the parent class default constructor. -- If the parent class explicitly includes a no-argument constructor, the child class can use the default constructor. When the compiler inserts the call super(), this code will compile, because a no-argument constructor has been explicitly coded in the parent class.

When a parent class does not include a no-argument constructor, the child class cannot use the default constructor. When the compiler tries to insert the call super(), it will fail since this call is not valid for the parent class. -- Each constructor that is included in a subclass must include a call to the parent constructor. If a cascading call to several constructors is used, the constructor that will finally execute must have the call to the parent constructor as the very first statement. Figure 3 identifies the different conditions constructors from subclasses and superclasses. for using

The call to a parent constructor is through the use of the keyword super. The format of the statement is to match at least one argument list of a constructor of the parent class. The name for the parent class is not used in this call. Since Java does not permit multiple inheritance, there can only be one parent to any subclass. The variable super has a reference to the parent class object and its definition. The sample code in Figures 4 and 5 demonstrates the correct and incorrect usage of the keyword super and constructors in the construction of a subclass. Figure 4:
1 class Parent 2{ 3 String name; 4 5 // constructor 6 Parent (String s)

7 8

{ name = s;

9 } 10 11 // some methods 12 } 13 14 class Child extends Parent 15 { 16 // NO CONSTRUCTORS 17 // OTHER METHODS 18 } 19

Figure 5:
1 class Parent 2{ 3 String name; 4 5 // constructor 6 Parent (String s)

7 { 8 name = s; 9 } 10 11 // some methods 12 } 13 14 class Child extends Parent 15 { 16 // null constructor 17 Child() 18 { 19 super("name unknown"); 20 } 21 // OTHER METHODS 22 } 23

The Child class in Figure 4 will not compile. The compiler will try to insert a null constructor and an implicit call to super().

Note that the Parent class does not have a null constructor. This is because the Parent class has an explicitly defined constructor. The Child class in Figure 5 will compile. The null constructor of the Child class has been overridden to call the Parent constructor, using super and passing the argument required by the Parent constructor. Constructors in subclasses can be overloaded. The example in Figure 6 illustrates the use of overloaded constructors that call the super constructor. Figure 6:
1 /** 2 * Java Program Person.java 3 * @author Cisco Teacher 4 * @version 2002 5 */ 6 public class Person 7{ 8 String name; 9 10 // null constructor

11 Person (){} 12 13 // some methods 14 } 15 16 /** 17 * Java Program: Student.java 18 * @author Cisco Teacher 19 * @version 2002 20 */ 21 class Student extends Person 22 {

23 private final String studentName; 24 private String grade; 25 private int studentID; 26 27 // constructor with three argument 28 /** 29 * @param name The student's name as a String 30 * @param grd The student's grade as a String 31 * @param id The student's id as an int 32 */ 33 Student(String name, String grd, int id) 34 { 35 super(); // call to parent constructor 36 studentName = name; 37 grade = grd; 38 studentID = id; 39 } 40 // constructor with two argument 41 /** 42 * @param name The student's name as a String 43 * @param grd The student's grade as a String 44 */ 45 Student(String name, String grd) 46 { 47 //99999 is the default for the studentID 48 //when no Id is known 49 this(name, grade, 99999); 50 } 51 52 // constructor with one argument 53 /** 54 * @param name The student's name as a String 55 */ 56 Student(String name) 57 { 58 this(name, "grade unknown"); 59 } 60 // OTHER METHODS 61 }

8.7 Extending Classes


.

8.7.1 Abstract classes


. As a programmer moves up the inheritance hierarchy, classes become more general and often more abstract. At some point, the ancestor class becomes so general that it becomes a guideline for other classes, rather than a definition for an object that can be used. When a class in a hierarchy serves as a framework or guideline for other classes, the class is defined as abstract. In this case, the class is not expected to be used to create objects that store data and do work. The class is used to set boundaries for definitions of other subclasses. It is viewed as a common framework for a set of related subclasses. Consider an electronic messaging system, such as fax, email, voicemail, and postal mail. The common feature of all the messaging classes is having a message. An inheritance hierarchy is shown in Figure 1.

A Message object must have information on how a message will be transported. Thus, the Message class serves as an abstract framework for all of the other subclasses. The ultimate goal of OO design is to factor out the common operations and data to a higher level in the inheritance hierarchy. As the common operations are factored out, it may become clear that the details of how the operations are implemented cannot be specified in a higher-level class. For example, in the message system, the display() method can be implemented in all of the subclasses. How is this implemented for the Message class? Clearly the method display() is an abstract concept. It is a framework to define inclusion of such a method in the subclass definitions. An abstract method is declared using the syntax shown in Figure 2.
1 /* 2 An abstract method is declared using the following syntax: 3 4 abstract method-name (arguments); 5 6 An abstract method does not have any body of code. 7 A class that has an abstract method must be declared abstract.

8 9 abstract class ClassName { } 10 11 */ 12 13 public abstract class AbstractDemo{ 14 15 public abstract double calculateInterest(double balance); 16 17 }//end AbstractDemo 18

An abstract method does not have any body of code. A class that has an abstract method must be declared abstract. The sample code shown in Figure 3 presents the Message class definition, including the abstract display method.
1 /** 2 * Java Program: Message.java 3 * @author Cisco Teacher 4 * @version 2002 5 */ 6 abstract class Message 7{ 8 String sender; 9 String receiver; 10 String subject; 11 12 /** 13 * @param from The from tag of a message as a String 14 * @param to The to tag of a message as a String 15 * @param topic The topic of a message as a String 16 */ 17 public Message(String from, String to, String topic) 18 { 19 sender = from; 20 receiver = to; 21 subject = topic; 22 } 23 24 // abstract display method 25 abstract void display(){} 26

27 // other methods 28 29 } // end class 30

Figure 4 sets out the guidelines for the creation of abstract classes. In the case of the messaging system, the abstract class Message can store sender, receiver, and subject information as data values.

These are concrete data. Programmers of many GUI classes use the abstract class design to move as many common methods and data into the superclass as possible.

Lab 8.7.1 Implement Abstraction in the Phase III of the Banking Application

Learning Objectives
In this lab activity, the student will discover the common fields and behaviors for different types of account classes. The student will use these generalizations to define abstract classes.

Description/Scenario
As the programmer moves up the inheritance hierarchy, classes become more general and probably more abstract. At some point, the ancestor class becomes so general that it is thought of as a guideline for other classes, rather than as a definition for an object that can be used. When the class in a hierarchy serves as a framework or guideline for other classes, the class is defined as abstract. In this case, the class is not expected to be used to create objects that store data and do work. The class is used to set boundaries for definitions of other subclasses. It is viewed as a common framework for a set of related subclasses. One of the goals of OOP design is to factor out the common operations and data to a higher level in the inheritance hierarchy. As the common operations are factored out, it may become apparent that the details of how the operations are implemented cannot be specified in the higher-level class. Abstraction in OO is accomplished in the definition of methods. Abstract methods define the return type, name and arguments but no code. An abstract method is declared using the following syntax: <modifiers> abstract <return-type> method-name (arguments); An abstract method does not have any body of code. Abstract classes contain at least one abstract method. A class that has an abstract method must be declared abstract using this syntax: <modifier> abstract class ClassName { } Abstract methods cannot be declared as final. Declarations of final indicate that the method, attribute or class is constant and cannot be changed. When a method is

declared as abstract the expectation is that this declaration will change in some sub-class. The compiler enforces this rule. The banking application business rules declare that a Customer can own 4 types of accounts. For many operations the specificity of the account type is not as important as that it is an Account type. All of the four types of accounts, will have some common properties, they include the variables id, type, and balance. However the methods for deposit and withdraw have to be modified to implement the rules for operating on the different types of accounts. Currently the Account class holds an attribute that represents the acct type. This char field holds the values S , C , L , O , I . We will no longer need this attribute. The class type will represent the account type. The attribute account type and the methods associated with this field will be deleted from all the classes. The Customer class methods that add, remove and retrieve accounts will now use the account type to implement the business rules and not the char values that previously were used to represent the account types. The Customer class is modified after all the Account subclasses have been implemented. Define the Account class as an abstract class. The Account will be the super class for different types of Account classes.

8.7.2 Final classes


. The keyword final was introduced in the definition of data values as constants. The keyword final always indicates that the object, method, or data cannot be changed. In inheritance models, the keyword final, when applied to the methods of a class, prevents the method from being overridden by any subclass. The keyword final, when applied to a class definition, prevents a class from being used as a superclass to derive subclasses. This class cannot be extended. There are several classes in the Java language that have been declared final. One of the most commonly used is the String class. This is shown in Figure 1.

A programmer does not expect to have this class extended to some other unpredictable extension of the String class. If a class must be used in a controlled manner, declare the class to be final. The wrapper classes, which wrap object methods around Java primitives, are also declared final and cannot be extended. This is shown in Figure 2.

Lab 8.7.2.1 Implement Inheritance to create the Savings and Investment subclasses
Learning Objectives
In this lab activity, the student will apply inheritance principles to extend concrete classes from abstract superclasses, and extend concrete classes from concrete super classes.

Concepts

Programmers arrive at abstract and concrete designs of classes in one of two ways: o Generalization, or discovery of general behaviors among classes o Specialization, or identification of specific adaptation of general behaviors or adoption of new behaviors in an inherited class When designing classes, common fields and behaviors lead to generalizations about the classes. These generalizations can be implemented through the design of parent classes also known as superclasses. Superclasses can then be designed to describe required and optional fields and behaviors. A superclass can be an abstract representation of common behaviors and data. Generalizations of classes into a superclass can be either concrete or abstract. The term abstract is applied to classes from which no objects are expected to be created. When the superclass is an abstract representation, no objects of this class will be created. Superclasses can also be concrete classes. This particular design of classes is often used, when the superclass could represent a number of objects, and the subclasses represent variations of this object. Subclassing can occur with both abstract and concrete classes. The keyword extends establishes the is a relationship with the parent class. In operating on objects that are part of a class hierarchy, several new keywords are used. The keyword extend is used to declare a class as a subclass of another. The keyword abstract is used to declare a class as an abstract representation. A keyword that allow a programmer to reference the particular object being operated on is the this keyword, and super is used to represent the attributes and behaviors of the parent class.

Overloading is the technique of providing multiple declarations of the same method, with different arguments. Overloading occur in a specific class. Overloading provides flexibility in the operations of an object, allowing for multiple inputs. Overriding is used only in the context of inheritance. Overriding is the technique of modifying a parent method in a subclass. These are the rules to remember as overloading and overriding are implemented in subclass designs. o Any method that is repeated in the subclass with the same name and different arguments is an overloading of the parent method in the child class. o Any method that is repeated in the child class, with the same name, arguments, and return type as that of the parent class is an overriding of the parent method. o Overriding of methods allows for specialized implementation in a subclass. o Abstract methods of the parent class must be overridden in a concrete implementation of the subclass. o When abstract methods of the parent class are not overridden in the subclass, the subclass must be declared abstract. o Static methods of a parent class cannot be overridden in a subclass. o Subclass class methods, overridden from the parent class, cannot be more restrictive in access than that of the parent method. For example if the parent class method is public, the subclass overridden version cannot be protected =, default or private. o Private methods of the parent class cannot be overridden in the subclass. o In order to maintain encapsulation, declare parent attributes as protected. o Abstract classes cannot be declared as final, nor can abstract methods.

o Constructors are not inherited in the subclass. The parent constructor must be called explicitly in any constructors implemented in the subclass. The call to the parent constructor is of the form super(). This must be the first statement in the subclass constructor. The class type will represent the account type. The attribute account type and the methods associated with this field will be deleted from all the classes. The Customer class methods that add, remove, and retrieve accounts will now use the account type to implement the business rules and not the char values that previously were used to represent the account types. The Customer class is modified after all the Account subclasses have been implemented.

Business Rules
In the lab, create a concrete Savings Account class from the abstract Account class defined in the previous lab. Several business rules are implemented in this class. o Savings accounts require a minimum balance of ten dollars. When a new customer joins the bank they are assigned a savings account and must deposit at least ten dollars. They can deposit more if they wish. Customers will be allowed to withdraw from the savings account at any time. Customers cannot withdraw amounts exceeding the amount in their account less ten dollars. The savings interest rates are calculated on daily basis depending on the premium interest rates set in the Bank class. o Implement a constructor in the Savings class that accepts a Customer object, which will be used to obtain part of the Account ID information, an amount that

represents the balance. The Account ID is given by CustomerID. We will no longer require that the account type is identified as part of the account ID. By creating very specific classes of the Account class, the class type serves this purpose. o The savings interest rate is 3% per year and it is calculated daily. Extend the Investment Account as a concrete class from the Savings class several business rules are implemented in this class. o Investment accounts are used to save money for an extended period of time. This account provides the customer with a higher interest rate based on how long they invest money in the account. The longer they keep the money in the account the higher the interest rate they will earn. Investment accounts require a minimum amount to open the account. The minimum amount is 100 dollars, and the minimum investment term is six months. An investment term is how long the money has to remain in the account without any withdrawals from the account. Investment interest rates are at 0-6 months at 5% and 6 -12 months at 6% and 12+ months at 7%. Interest calculation is compounded monthly. The penalty for early withdraw is 20%.

8.8 Interfaces
8.8.1 What and why of interfaces
As stated earlier, Java does not allow for multiple inheritance. Consider a Programmer class. This class represents individuals who are part of the Employee group of an organization. If a Programmer has to be represented as a Spouse in one context, an Employee in another, and a Programmer in yet another, Java would not enable this through inheritance. A Programmer class cannot extend from both a Spouse class and an Employee class, even though a programmer could be both a Spouse and an Employee. If a programmer is described as both a Spouse and an Employee, this generally refers to the operations or behaviors that are associated with these classes. While all the data pertinent to a programmer could reside in either the parent class Spouse or the parent class Employee, it should be possible to represent a Programmer as a Spouse in some contexts and as an Employee in others. This requires a way to create an object that holds data representing the Programmer class and can also perform operations associated with a different class of objects. The Java language provides an interface facility for implementing multiple inheritance, which is deriving behaviors from two unrelated classes. Interfaces enable multiple inheritance of behaviors from different classes and serve as a design document for external features of a class. Interfaces are abstract classes that define abstract methods and constants. All of the methods in an interface must be public.

An interface can include constants, but no other types of attributes. Interfaces provide a mechanism for a subclass to define behaviors from sources other than the direct and indirect superclasses. Interfaces can be used to perform these tasks: -- Capture similarities among unrelated classes without artificially forcing a class relationship -- Declare methods that classes are expected to implement -- Reveal the programming interface of an object without revealing its class Consider the example of classes that describe things that fly. Flying includes actions such as taking off, landing, and flying. An interface can be created which defines all of theses actions in the form of abstract methods. Things that fly can include a bird, an airplane, and a helicopter. Each object takes off, lands, and flies differently. The bird flaps its wings, the airplane uses the thrust from an engine, and the helicopter utilizes a rotor blade. Each flying thing implements a different procedure for what seems to be common and similar actions. An interface such as the Flyer interface can define these common methods. Each of the classes implements this interface. Figure 1 shows the inheritance relationship between the Flyer interface and the classes.

In addition to implementing a Flyer interface, each of these objects is part of its own superclass/subclass hierarchy. Figure 2 illustrates how the classes relate to their inheritance hierarchies and to the interface implementations.

In this example, one can agree that an Airplane is not an Animal and a Bird is not a Vehicle, but a Bird and an Airplane are both Flyer objects. A class must implement all the methods that are declared in the interface or the class must be defined as abstract. In the Animal inheritance hierarchy some of the subclasses, specifically the Fish and Cat classes, can be considered pets. These classes have common behaviors that relate to being a pet. A Pet interface could be added to the class design in order to address these common methods. Figure 3 illustrates the inheritance relationship between this new Pet interface and the other classes in the Animal inheritance hierarchy.

8.8.2 Object class


. The syntax for implementing an interface includes the use of the keyword implements in the class definition statement. Implementing interfaces is more than the declaration in the class definition statement. This declaration is viewed as a contract between the class that implements the interface and the interface itself. The compiler enforces this contract by ensuring that all methods declared in the interface are also implemented in the class. In some cases, this may include a null implementation. A null implementation is an implementation of a method definition without any procedural code. For example, since fish do not play, a null method implementation is used to satisfy the contract between the Fish class and the Pet interface. This is shown in Figure 1.

Methods declared in an interface are always public. The compiler will automatically insert the access modifier public.

When an interface method is implemented in a class, it is a common error to use the default access modifier similar to the interface declaration. This will result in a compiler error since the default access modifier for a class method is default level access, also known as package access, which the compiler will identify as a weaker access level then the required public access. Figure 2 summarizes the implementation of an interface.

8.9 Polymorphism, Dynamic Binding, and Virtual Method Invocation


.

8.9.1 Polymorphism
. Polymorphism literally means "many forms". Polymorphism is a mechanism in the Java language that adds enormous flexibility to programs. To understand the concept of an object assuming many forms, review the code in Figure 1.

Note that there are objects of one class being represented by reference variables that are of a different class. These statements are constructing objects that can be handled in different ways depending on the reference type. The second row in the table shows some objects that are created. In the first statement, the object is actually a Bird. The object will have all the attributes of the Bird class and the Animal class. In this statement, the reference to the object is through the variable of the type Animal. This

statement to means that the object Bird, in this context will be seen only in the form of the Animal. The only behaviors and attributes accessible will that of the Animal part of the object. In the second statement, the object created is an Eagle and the reference to the object is of the type Flyer. In this context, the object will take on the form of the Flyer and the behaviors of the Flyer are all accessible through the reference variable. Each of these statements shows that although an object is of a particular type, the form it takes is based on the reference type used to access the object. The third row illustrates another perspective of polymorphism. In this row, the objects created in the first row are cast in a different form. For example the first statement casts the Bird object as its true form bird. The object is seen as a bird and in the second row, this same object is referenced as an Animal. Observe that any object can be referenced by any of the forms that the class implements or inherits. The object Bird can be seen as an Animal, a Bird, or a Flyer. In general terms, polymorphism allows the same code to have different effects at run-time depending on the context. Polymorphism takes advantage of inheritance and interface implementations. Polymorphism is best understood in the context of code. In Figure 2, polymorphism is used in object creation.

In this example, assume the Employee class and the Teacher class both have a method getDetails(). The code for each one is different. The Employee class getDetails() method returns a String that contains the identification and name of each employee. The Teacher getDetails() method returns an identification, name, classroom, and grade. If e1.getDetails() and

t1.getDetails() are called, different behaviors are exhibited and different results are returned. It is not obvious what happens with e2. The object referenced by e2 is an example of polymorphism. Here the variable e2 is of the type Employee. The actual object created and resulting object reference assigned to e2 is a Teacher object. At run-time, the e2.getDetails() will result in the invocation of the getDetails() method of the Teacher object. This is known as dynamic method invocation or virtual method binding. The method that is executed is the method of the object, and not the method of the class of the reference variable. Another contextual use of the polymorphism concept is in the context of method calls. In Figure 3, the School class has a method display(Employee e).

1 /** 2 * This class uses Employee and Teacher objects 3 * @author Cisco Teacher 4 * @version 2002 5 */ 6 public class School 7{ 8 /** 9 * @param e The Employee object 10 */ 11 public String display(Employee e) 12 {

13 System.out.println(" The employee information is: "); 14 System.out.println(e.getDetails()); 15 } 16 17 /** 18 * @param t The Teacher object 19 */ 20 public String setClassroom(Teacher t) 21 { 22 t.setClassroom("room "); 23 } 24 25 public static void main(String args []) 26 { 27 Employee e1 = new Employee(); 28 Teacher t1 = new Teacher(); 29 Employee e2 = new Teacher(); 30 31 School s1 = new School(); 32 33 e1.getDetails(); 34 t1.getDetails(); 35 e2.getDetails(); 36 37 s1.display(t1); 38 s1.display(e1); 39 s1.display(e2); 40 41 s1.setClassroom(t1); 42 /* 43 The next statement will not work 44 because e1 holds a reference to an 45 Employee object. 46 */ 47 s1.setClassroom(e1); 48 49 /* 50 The next statement will work 51 because e2 holds a reference to 52 cast e2 to a Teacher. 53 */ 54 s1.setClassroom(e2); 55 } 56 57 } // end of School class 58

This method accepts objects of the type Employee. In the call to this method, line 37 passes the reference to an Employee object and line 38 passes a reference to a Teacher object. This works in this statement because a Teacher is an Employee. Line 39 passes the variable e2, which is of the type Employee, but holds a reference to a Teacher object. The class named School has a method setClassroom(Teacher t). This method accepts references to objects of the type Teacher. Line 41 will work because t1 references a Teacher object. Line 47 will not work. While a Teacher is an Employee, not all employees are Teachers. As a result, the Employee object is not always a Teacher object. Inheritance only works in one direction, from superclass to subclass. A method that receives an object of a type can be called with objects that are subclasses of that type, but not more general or superclasses of the type. Line 54 works because it holds a reference to a Teacher object, even though the variable e2 is of the type Employee. Another way objects work together is by defining methods that take other objects as parameters. More cooperation and efficiency occurs when the objects are united by a common superclass. All classes in the Java programming language have an inheritance relationship. For example, a method that is defined to take java.lang.Object as a parameter can accept any object in the Java platform. This form of cooperation is called polymorphism.

8.9.2 Virtual method invocation or dynamic method binding


. The technique of resolving the behaviors of an object at run-time is known as dynamic method binding, or virtual method invocation. This is a key feature of polymorphism.
1 /** 2 * This class uses Employee and Teacher objects 3 * @author Cisco Teacher 4 * @version 2002 5 */ 6 public class School 7{ 8 /** 9 * @param e The Employee object 10 */ 11 public String display(Employee e) 12 { 13 System.out.println(" The employee information is: "); 14 System.out.println(e.getDetails()); 15 } 16 17 /** 18 * @param t The Teacher object 19 */ 20 public String setClassroom(Teacher t) 21 { 22 t.setClassroom("room "); 23 } 24 25 public static void main(String args []) 26 { 27 Employee e1 = new Employee(); 28 Teacher t1 = new Teacher(); 29 Employee e2 = new Teacher(); 30 31 School s1 = new School(); 32 33 e1.getDetails(); 34 t1.getDetails(); 35 e2.getDetails();

36 37 s1.display(t1); 38 s1.display(e1); 39 s1.display(e2); 40 41 s1.setClassroom(t1); 42 /* 43 The next statement will not work 44 because e1 holds a reference to an 45 Employee object. 46 */ 47 s1.setClassroom(e1); 48 49 /* 50 The next statement will work 51 because e2 holds a reference to 52 cast e2 to a Teacher. 53 */ 54 s1.setClassroom(e2); 55 } 56 57 } // end of School class 58

In the code for the School class, line 29 will create a variable that is a reference of the type Employee. However, at runtime, the call to the e2.getDetails() on line 35 will invoke the method of the Teacher class. This is because on line 29, the object that was created is a Teacher object. Dynamic binding resolves which method to call at runtime when more than one class in an inheritance hierarchy has implemented the method. The JVM looks at the type of object for which the call is made, not the type of object reference in the calling statement. So in line 29, e2 is a reference of the type Employee in the calling statement, but the object being called is a Teacher object. Therefore, the Teacher version of the getDetails() method is used.

Dynamic binding also resolves the handling of the arguments being passed to a method. Again, the JVM looks at the type of object being passed by value as an argument, not the reference type of the variable being passed as an argument to the method. In line 54, the method argument e2 is a reference variable of the type Employee. However, the object actually being referenced is a Teacher object and the method setClassroom(), which requires a Teacher argument, is successfully invoked.

You might also like