Professional Documents
Culture Documents
Reproduction and/or distribution in whole or in part in electronic, paper or other forms without written permission is prohibited.
Reprinted for Balaji Nallathambi, Verizon Balaji@verizon.com Reprinted with permission as a subscription benefit of Books24x7, http://www.books24x7.com/
Table of Contents
Point 18: Designing Java Applications Using Abstract Classes and Interfaces........................1 ObjectOriented Programming in Java..........................................................................................2 Abstraction and Encapsulation...............................................................................................2 Reusability..............................................................................................................................4 Polymorphism.........................................................................................................................9 Abstract Classes .............................................................................................................................10 Variables and Methods in Abstract Classes.........................................................................10 Extending Abstract Classes and Implementing Interfaces ....................................................10 Extending Classes from Abstract Classes............................................................................10 Importance of Abstract Classes............................................................................................11 Interfaces .........................................................................................................................................12 Variables and Methods in Interfaces .....................................................................................12 Extending Interfaces.............................................................................................................12 Implementing Interfaces ........................................................................................................12 Blank Interfaces....................................................................................................................13 Importance of Interfaces.......................................................................................................14 Inner Classes........................................................................................................................16 Dynamic Method Lookup in Abstract Classes and Interfaces...................................................18 Comparing Interfaces and Abstract Classes...............................................................................21 Related Topics................................................................................................................................23
Point 18: Designing Java Applications Using Abstract Classes and Interfaces
Suchit Malhotra Java is an objectoriented programming (OOP) language similar to C++. Some features of C++ are not present in Java, such as multiple inheritance and pointers. Java uses interfaces to provide the function of multiple inheritances. Java also supports abstract classes, which are used to provide common behavior in an inheritance hierarchy. This ReferencePoint discusses the concept of objectoriented programming in Java. It describes abstract classes and interfaces and how to build an application using these concepts. It also compares interfaces with abstract classes.
public: Makes the variables or methods available to every class, which either makes the instance of the class or inherits the class. private: Makes the variables or methods available to only the class members of the current class. The other classes, which either inherit from the class or make the object of class, do not have access to private variables. The inherited subclasses can only access the private members of the parent class through the public or protected members of the parent class.
protected: Makes the variables or methods available to the subclasses and the classes in the same package.
Listing 2181 defines a class, Test, with public methods: Listing 2181: Defining the Test Class
public class Test { private int x; public Test() { this.x=0; } public void set X (int x) { this.x=x; } public int getX() { return this.x; } }
This code shows that the Test class consists of the data member x, which is encapsulated using the private keyword. The public methods are getX() and setX(int x), which return and set the value of the private variable x.
Note The this keyword points to the object calling the method. Listing 2182 defines the UseTest class, which creates objects of the Test class in Listing 2181: Listing 2182: Defining the UseTest.java Class
public class UseTest { public static void main(String args[]) { Test obj=new Test(); System.out.println(obj.getX()); obj.setX(5); System.out.println(obj.getX()); } }
In this code, the UseTest class creates the obj object of the Test class in Listing 2181. The obj object calls the methods of the Test class to access and manipulate the value of x, the private variable. The obj object uses the getX() and setX() methods to return and set the state of the object, which is the value of the private variable x. The obj object accesses the value of x and the program prints it to the console, as shown in Figure 2181:
Reusability
Reusability refers to using existing classes to simplify the coding of an application. New classes in an application can also use existing classes. The advantage of existing classes is that they have already been written, tested, and debugged. There are many ways of reusing existing classes in objectoriented programming, such as association, inheritance, metaclass, aggregation, and instantiation. Inheritance Inheritance is the process in which a class acquires the attributes and behavior of an existing class. Making classes share the common properties of some other classes reduces the overall complexity of the application development process. For example, a vehicle class shares the common properties of motorcycle, car, bus, and truck. These vehicles have various properties, such as brand name and engine, which can be included as the attributes of the common Vehicle class. Inheritance is an important part of objectoriented programming because it reduces the application development process to coding independent modules, which can be written by different programmers and integrated to create the application. The classes in the inheritance hierarchy are divided into two parts: Base Class: This is also known as the parent or superclass. It is at the upper level in the inheritance hierarchy of classes. This class is the class from which another class derives itself. For example, the Vehicle class is the parent class of the Car class. Derived Class: This is also known as the child class or sub class. It is at a lower level in comparison with some other class of the inheritance hierarchy. This class derives the properties of the base class. For example, the Car class is the derived class from the Vehicle class.
There are various types of Inheritance hierarchy possible in OOP. Some of them include:
Single inheritance: Occurs when a derived class inherits from the single base class. MultiLevel inheritance: Occurs when a base class of any class is derived from another class. Multiple inheritance: Occurs when a derived class inherits from multiple base classes. Hierarchical inheritance: Occurs when multiple derived classes have the same base class.
Note Java supports all types of inheritance except multiple inheritance. In Java, inheritance is used for two purposes, class inheritance and interface inheritance. Java uses the extends keyword to inherit the classes from previously written and compiled classes and interfaces from previously written and compiled interfaces. Java supports multiple inheritance in case of interface inheritance but not in class inheritance.
Note
The number of classes in Java is constantly increasing. To avoid running out of names for classes, Java uses the concept of a package. A package contains a set of classes. The package can be explicitly imported in any class using the import keyword.
The object class is the superclass for every class written in Java. You do not need to explicitly extend your classes from the object class. Because every class in Java is a subclass of the object class, the instances of the object class can refer to the objects of any class. This property enables you to use the objects of the Object class when you need to implement the flexibility of using any class in the future. There are many useful methods in the object class, which can be overridden in any class in Java. Listing 2183 shows how the properties of one class are inherited into another: Listing 2183: Inheriting the Properties of One Class into Another
class Employee { public Employee(String name, int age, double { this.name=name; this.age=age; this.pay=pay; } public void show() { System.out.println("Name: "+name); System.out.println("Age: "+age); System.out.println("Pay: "+pay); } public void incrPay(double percent) { this.pay*=1+percent/100; } public void incrPay() { this.pay+=1000; } public String name; protected int age; private double pay;
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
pay)
This code contains the Employee class, which contains the member variables name, age, and pay with different access modifiers to get data for any employee. The Employee class contains the show() method to show the data members in the class, the incrPay(int Percent) method to increase the value of member variable pay by a specified percent, and the incrPay() method to increase the value of pay by 1000. The Employee class has its own constructor to initialize the values of the member variables of the class. Each class in Java has a default constructor that does not contain any arguments provided by the Java run time environment (JRE). If a class does not have a constructor, the default constructor is provided implicitly. If a class has a constructor with parameters, the framework does not provide the default constructor without argument. You need to write the constructor without the argument. Writing different constructors in a class is known as constructor overloading. The JRE creates the object of the parent class each time the child class is instantiated. If the parent class does not have a constructor, the implicit default constructor creates the object of the parent class. When the parent class defines a constructor with an argument, the JRE cannot create a parent class object for the child class. The child class constructor calls the constructor with the argument of the parent class explicitly using the super keyword to create the parent class object. Listing 2184 shows how to create the Manager class, which inherits from the Employee class of Listing 2183. This code shows how to call the parent class constructor using the super keyword from the child class constructor.
Listing 2184: Creating the Manager.java Class
public class Manager extends Employee { public Manager(String name, int age, double pay, String area) { super(name,age,pay); this.area=area; } public void show() { super.show(); System.out.println("Name of Manager: "+ name); System.out.println("Age of Manager: "+ age); //System.out.println("Pay of Manager: "+ pay); System.out.println("Area of Posting: "+ area); } public static void main(String ar[]) { Manager m1=new Manager("Sam", 24, 3000, "Washington"); m1.show(); m1.incrPay(100); m1.show(); } private String area; }
This code creates the Manager class, which is the subclass of the Employee class in Listing 2183. The Manager class inherits the members of the Employee class. The Manager class contains the area member variable, which cannot be a part of the Employee superclass because this attribute is not common to all employees. The Manager class calls the constructor with the argument of Employee class in its constructor and passes the values of name, age, and pay. This creates the Employee class object for the Manager subclass. The constructor also sets the value of area with the passed value. If the Manager class constructor does not call the Employee class constructor explicitly, the JRE cannot create an Employee class object for the Manager class.
The show() method of the Manager class overrides the show() method of the parent class. It calls the show() method of the parent class to display the values of name, age, and pay. It contains the code to display the values of name, age, and area. The variable area is the member variable of the Manager class. The Manager class also has access to the protected variable age and the public variable name of the Employee parent class. In addition, the Manager class does not have the access to the pay variable because it is the private variable of the Employee parent class. The reference to the pay variable from the Manager class causes a compiletime error. The incrPay(int percentage) method is the member of the Employee parent class. It does not have any definition in the Manager class. The Manager class has the access to this method because it is declared as a public member in the parent Employee class. The call to this method refers to the parent class method. Figure 2182 shows the output of the code in Listing 2184:
Figure 2182: Output of the Manager.java class Java supports the usage of the static methods and variables, also known as class methods and class variables, respectively. Java uses the static keyword to declare a method or a variable as static. Static variables are instantiated only once when a class is loaded in the memory. If you do not explicitly provide any values in the class, static variables are instantiated with their default values. The default value of the static members differs with their types. For example, the default value for the integer type static variable is 0. Static methods are also instantiated when the class is loaded in the memory. Although a static method cannot access the instance members of the class, it can access other static methods and variables. The class name or any instance of the class can invoke a static method.
Note In Java, the main method is always declared as static because it is called by the interpreter before instantiating the class. Java uses the final keyword in the class declaration to prevent the inheritance from a class. The classes declared with the final keyword are final classes. Final classes cannot act as the parent class to any other class. For example, if the Employee class in Listing 2183 is a final class, the inheritance of the Manager class in Listing 2184 from the Employee class is not possible. Final classes make programs run faster because they enable the compiler to perform static binding. Aggregation Aggregation is a technique to enable code reusability. Although it is a special type of association among classes, this relationship may or may not show physical containment among classes. In contrast to inheritance, the objects in aggregation exist independent of each other. Java implements aggregation by making the instances of classes in other classes. Listing 2185 shows how to avoid using inheritance:
Listing 2185: Avoiding the Usage of Inheritance in the Manager.java Class
public class Manager { public Manager(String name, int age, double pay, String area) { this.emp=new Employee(name,age,pay); this.area=area; } public void show() { emp.show(); System.out.println("Name from Manager: "+ emp.name); //System.out.println("Age from Manager: "+ age); //System.out.println("Pay from Manager: "+ pay); System.out.println("Area of Posting: "+ area); } public static void main(String ar[]) { Manager m1=new Manager("Sam", 24, 15000, "Washington"); m1.show(); m1.emp.incrPay(100); m1.show(); } private String area; private Employee emp; }
In this code, the Manager class makes an object of the Employee class a member variable and initializes it by passing the necessary values of name, age, and pay variables in the constructor. The super keyword is not used because the Employee class is not a superclass of the Manager class. The show() method of Manager class is not related to the Employee class show() method. The names of both methods are identical only for symmetry. In Listing 2184, the Manager class uses the super keyword to call the Employee class show() method, while the Manager class in Listing 2185 doesn't use the super keyword. The emp member variable calls the show() method of the Employee class. In addition to the private variable, pay, the reference to the protected variable, age, is also made a comment because the classes inherited from the specified class can access the protected members of its parent class. You cannot reference the incrPay(int percent) method directly by the object of the Manager class. The call to the incrPay() method is made through the Employee class object emp.
In Listing 2184 and Listing 2185, the Manager class uses the Employee class to show different types of reusability. It is difficult to choose between the design strategies, inheritance and aggregation. One of the main factors that determine the choice is the type of the relation between the classes. Inheritance is used when the 'isa' relationship is maintained between the classes throughout the lifetime of objects. Reusability is best achieved through the aggregation with interface implementation because it makes code debugging and altering easier than inheritance.
Polymorphism
Polymorphism refers to the programming language's ability to use same name for the variable, object, or function. Objectoriented programming supports the use of the same operator and method in different ways, depending on the data type with which it is used. Polymorphism is applicable only when there are two different methods with the same name. Polymorphism is of two types: Compile Time: Achieved when the called method is replaced with a memory address at compile time. Method overloading results in compile time polymorphism. Method overloading occurs when the same class contains more than one method with the same name and return type. The method must differ in the type and number of parameters. For example, in Listing 2183, the Employee class contains two different definitions for the incrPay() method. If a class calls the incrPay() method by passing one double type argument, the value of the pay variable is increased by the percent that is passed as an argument. If the incrPay() method is called without an argument, the value of the pay variable increases by 1000. Run Time: Achieved when the run time environment determines the call method by calling the appropriate method that matches with the object. The run time environment decides the method call by the object, which is overriding results in runtime polymorphism. Method overriding means that a child class in the inheritance hierarchy contains a method with the same signature as that of the parent class method. The method signature is a combination of method name, return type, and the type and number of parameters of the methods. For example, in Listing 2184, the Manager class overrides the show() method of the Employee class. Note that the show method of Manager class in Listing 2185 is not an example of method overriding because the Employee class is not the parent class of the Manager class.
Polymorphism also exists in operators. Java provides operator overloading in the builtin classes. For example, the + and = operators work with the String class. The JRE decides the type of operator by the type of operands. Java uses final methods to stop method overriding. The final keyword is used in the method definition of the parent class to stop method overriding by the child class. A method is generally declared as final if the method behavior in the class works for the child classes also. Child classes do not need to change the behavior of the method.
Abstract Classes
An abstract class is a class used as an intermediate between a normal class and an interface. An abstract class is defined using the abstract keyword. A class with an abstract method must be declared abstract. An abstract method does not have a body. The syntax to declare an abstract class is:
<modifier> abstract class <name> {extends <superclasses>}{implements<superinterfaces> ,.......} { <method header>{<method body>}........... <variable declaration>........... }
The abstract class cannot be instantiated using the new keyword because the class may or may not have the method definition for all the methods. The references of the abstract class type can be formed using the child class objects. By default, the access modifier in an abstract class is public. You cannot use private or protected modifiers with abstract classes because they are derived by some class.
11
Note
The adapter KeyListener class is defined as an abstract class, similar to other adapter classes, such as MouseAdapter and FocusAdapter.
Listing 2186 shows the sample code to use an adapter class: Listing 2186: Using an Adapter Class
import Java.awt.event.*; import Java.applet.*; /* <applet code="UseAdapter"width=300 height=100> </applet> */ public class UseAdapter extends Applet { public void init() { addKeyListener(new SmallListener(this)); } } class SmallListener extends KeyAdapter { UseAdapter useAdapter; public SmallListener(UseAdapter useaAapter) { this.useAdapter=useAdapter; } public void keyPressed(KeyEvent ke) { /* necessary implementation using object useAdapter*/ } }
This code contains the UseAdapter and SmallListener classes. In addition, the source and listener are different classes. The listener class extending from the adapter class makes a handler of the source class to perform the necessary operations on the corresponding events.
Interfaces
Java uses interfaces to provide the features of multiple inheritance because classes in Java cannot have more than one superclass. In Java, an interface is a keyword used to define a collection of method definitions and constant values. Interface enables a class to reflect the behavior of more than one parent class. That is if a class is inheriting from more than one class then it can implement an interface as well.
Note
In Java, names of interfaces start with a capital letter and end with the able or ible suffix.
Java uses the keyword interface to define an interface. The syntax to declare an interface is:
<modifier> interface <name> {extends <super interface>,.....} { <method header>........... <constant declaration>........... }
In this syntax, the modifier can be either public or private. The other access modifiers, protected and private, are not used in the interface declaration because a class implements interfaces. This class must be available to all the classes for implementation. Although the public modifier makes the interface available to any class, not using the modifier makes the interface available only to the package in which the interface is declared. Interfaces also use the extends keyword to extend from the other interfaces.
Extending Interfaces
An interface can inherit from other interfaces using the extends keyword. Multiple inheritance is also possible because Java enables an interface to inherit the properties of multiple interfaces. The syntax to inherit interfaces is the same as that to inherit a class. If an interface extends from multiple interfaces, a comma separates each parent interface in the declaration of the child interface.
Implementing Interfaces
Classes can use interfaces by implementing them. A class can implement multiple interfaces using the implements keyword. A class can specify a number of parent interfaces separated by a comma after the keyword implements in the class declaration. A class that implements one or more interfaces must provide a definition to all the methods of the parent interfaces. An abstract class can implement interfaces without giving body to all the methods of parent interfaces.
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
13
Blank Interfaces
Blank interfaces are also known as marker interfaces. These interfaces do not contain any body, that is, they do not contain any method or variable. A class can implement a blank interface to provide additional information about itself. A blank interface tags the classes to show similar behavior. Java APIs provide several blank interfaces. For example, cloneable is an important blank interface used to make a clone of an object of any class. The object class in Java consists of the clone() method, which is used to make a bitwise copy of the object. The clone() method is a protected method of the class object. To use the clone method efficiently in a class, you need to implement the cloneable interface. Although the default clone method makes a bitwise copy of the object, you need to override the clone method to clone objects efficiently. You need to do this because the bitwise copy does not always work properly. Sometimes, a class contains the object of another class. For example, the cloning of the object of the Employee class in Listing 2183, which uses the default clone() method, works properly because this class consists of default data types. Listing 2187 shows how to clone the employee class in Listing 2183: Listing 2187: Cloning the Employee Class
Employee emp1= new Employee("Sam",24,3000); Employee emp2= emp1; Employee emp3= (Employee) emp1.clone();
This code makes an object, emp1, emp2, and emp3, of the employee class. The objects emp1 and emp2 both refer to the same memory location. Any change in either of them changes the other object. For example, if the pay of emp1 is incremented using the incrPay(int percent) method of the employee class, the pay of emp2 will automatically increase by the same percent. The cloned object emp3 solves this problem by making a bitwise copy of emp1. Both emp1 and emp3 refer to different memory locations. A change in one of them does not affect the other. Listing 2188 shows how to clone the Manager class, as shown in Listing 2185: Listing 2188: Cloning the Manager Class
Manager man1= new Manager("Sam", 24, 3000, "Washington"); Manager man2= man1.clone();
This code creates clone man2 of the object man1 of the Manager class. This clone displays an incorrect output. The Manager class contains two data members, one of which is an object of Employee class. The clone man2 makes a bitwise copy of the object man1 of the Manager class. It copies the corresponding String type area variable, but it only copies the address of the Employee variable. Both the original object and the clone share the same employee object. The cloneable interface solves the above problem. For example, both the Employee and Manager classes can override the clone method by implementing the cloneable interface. Listing 2189 shows how the changed Employee class supports the cloning of the object of the Manager class: Listing 2189: Cloning the Object of the Employee Class
Public class Employee implements Cloneable {
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
14
// The code provided in the Listing 2183 public Object clone() { try { //calls the object class clone method return super.clone(); } catch(CloneNotSupportedException _exp) { //this exception does not happen return _exp; } } }
This code contains the implementation of the clone method in the changed Employee class by implementing the cloneable interface. The clone method in this class calls the default clone method of the object class because all the member variables of the Employee class are cloneable. Listing 21810 shows how the changed Manager class can support the cloning of the object of the Manager class: Listing 21810: Cloning the Object of the Manager Class
public class Manager implements Cloneable { public Object clone() { try { Manager m= (Manager) super.clone(); m.emp= (Employee) emp.clone(); return m; } catch(CloneNotSupportedException _exp) { //this exception does not happen return _exp; } } }
This code contains the changed manager class, which implements the cloneable interface. The manager class overrides the clone method and does not call the default clone method. The clone method in this class makes an object, m, of the manager class using the clone method of the object class. The employee variable emp of the object m is cloned again using the clone method that was overridden in the employee class. The clone method returns the object m of the manager class. The clone method separately clones the employee class variable because cloning the manager class object creates copies of the address pointing to the employee class object.
Importance of Interfaces
The event delegation model in Java defines two parts, source and listeners. When an event occurs, the event source invokes the appropriate method defined in the class that implements the necessary event listener interfaces. There are several event listener interfaces present in the Java event delegation model. When a listener class implements an event listener interface, it provides body to every method defined in the listener interface. For example, if a class implements a KeyListener interface, it defines the following methods:
void keyPressed(KeyEvent ke)
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
15
You must register listeners using the addXXXListener(Object obj) methods, which are provided for each listener interface. Note XXX is used as a generalized notation for a set of similar words in Java. For example, XXX in addXXXListener is used as a common notation for Key, Mouse, and Window. Listing 21811 shows how to use a Listener interface:
Listing 21811: Using Listener Interface
import Java.awt.*; import Java.awt.event.*; import Java.applet.*; /* <applet code="UseListener"width=300 height=100> </applet> */ public class UseListener extends Applet implements KeyListener { public void init() { addKeyListener(this); } public void keyPressed(KeyEvent ke) { // necessary implementation } public void keyReleased(KeyEvent ke) { // necessary implementation } public void keyTyped(KeyEvent ke) { // necessary implementation } }
This code contains the UseListener class, which implements the KeyListener interface and defines all the methods of the interface. The addKeyListener method is used to register the key listener. The applet acts as both the source and listener in this example. Interfaces are used to make callbacks in Java. The callback is a mechanism where a method in one object asks a method in another object to notify when an event happens, as shown in Listing 21812: Listing 21812: Implementing Callbacks in Java
interface Inter { public void show(); } class Existing { Inter inter; Existing(Inter inter) { this.inter=inter; } public void useCall() { inter.show(); } } class CallBack implements Inter
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
16
This code defines an interface named inter that calls back the CallBack class, which implements this interface. The Existing class makes a reference to Inter interface and uses this reference to call the show() method. The object of the CallBack class initializes this interface reference. The object of the Callback class is passed to the Existing class in the constructor of the CallBack class.
Inner Classes
The inner class is a class that is defined inside another class. The interfaces can also be defined within a class definition. The Java compiler handles inner classes. The Java Virtual Machine (JVM) visualizes the inner class as a simple class. Inner classes can be categorized as nonstatic inner, static inner, or anonymous. Nonstatic Inner Classes Nonstatic inner classes can access all the variables and methods, including the private members, of the class containing it. The inner classes can refer these private members of the outer class the same way as they reference their own class members. Nonstatic inner classes are hidden from the other classes in the same package. The object of nonstatic inner classes is created in the context of an instance of the class enclosing it. A nonstatic inner class can be defined as public, protected, and private. In Java, you can define local classes that are defined in a block. These classes are completely hidden from the outside and cannot be accessed even from other parts of the same class outside the block. Static Inner Classes Static inner classes are made when the inner classes do not need the reference to the outer class object. These classes are similar to a normal inner class, except that a static inner class is defined using the static modifier in the class. Java supports a static interface definition within a class. The classes and interfaces can be nested to any depth within the toplevel class. The interfaces in Java are implicitly static. The static inner classes and interfaces can be referenced from outside the class. The toplevel class or other nested classes can be imported in a program using the import keyword. Anonymous Classes Anonymous classes combine the definition and instantiation of a class. These classes do not have a name and are instantiated by returning the object of the parent, which can be a class or an interface. Listing 21813 shows how anonymous classes are used in Java: Listing 21813: Using Anonymous Classes
interface ParentI { public void show(); } class ParentC implements ParentI {
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
17
public void show() { System.out.println("Parent class show"); } } class UseParent { public ParentC anonymous1() { return new ParentC() {}; } public ParentC anonymous2() { return new ParentC() { public void show() { System.out.println("Anonymous2 show"); } }; } public ParentI anonymous3() { return new ParentI() { public void show() { System.out.println("Anonymous3 show"); } }; } } public class AnonymousClass { public static void main(String ar[]) { ParentI[] parentI={new UseParent().anonymous1(), new UseParent().anonymous2(), new UseParent().anonymous3() }; for(int i=0; i<parentI.length; i++) parentI[i].show(); } }
The above code consists of an interface, ParentI, and a class, ParentC, which implements the ParentI interface. Both act as the parent for the anonymous classes. The UseParent class defines three methods, anonymous1(), anonymous2(), and anonymous3(), which return the object of the three new anonymous classes. The anonymous1() method returns an object of the anonymous child class of the ParentC class, which uses the default show() method of the parent class. The anonymous2() method returns an object of the anonymous child class of the ParentC class, which overrides the show method of the parent class, ParentC. The anonymous3() method returns an object of the anonymous child class of the interface ParentI. This child class provides a definition for the show() method of the parent interface. The AnonymousClass is a public class that defines the main method. The references of the ParentI interface are created in the main method using all the three methods of the UseParent class.
Dynamic method binding is a process in which the run time environment determines the method call. This type of binding occurs when there are multiple definitions available for the same method in the inheritance hierarchy of the class. A class or an interface reference in Java can refer to any object in the inheritance hierarchy associated with the class or the interface. The process of referring an object to any other object in the inheritance hierarchy is known as casting. There are two types of casting: Upcasting: Assigns the subclass reference to the superclass reference. Here, the word superclass refers to a class or an abstract class or interface and the subclass is a class that either extends from the class or implements the interface. Downcasting: Assigns the superclass reference to the subclass reference.
In addition to the assignment of the class reference, you can also assign an interface type either to a reference of the object class or to the reference of the parent interface. In addition, you can cast a source array type into an object class reference. You can also cast an array into another array type if the conversion of a source array type into this array type is possible. When an object refers to a method, the compiler checks whether or not this method belongs to the class of that object. If the method is not present in the class, the compiler attempts to find the method definition in the inheritance hierarchy of the class. Listing 21814 shows how to implement casting and dynamic method binding: Listing 21814: Implementing Casting and Dynamic Method Binding
interface TopInter { public void show(); } abstract class Abs { public abstract void show(); public void show(String s) { System.out.println("Abstract class Abs : "+ s); } } interface Inter extends TopInter { } class Class1 extends Abs implements Inter { public void show() {
Reprinted for v697039, Verizon SkillSoft, SkillSoft Corporation (c) 2002, Copying Prohibited
19
System.out.println("Class Class1"); } public void show(String s) { System.out.println("Class Class1 : "+ s); } } class Class11 implements Inter { public void show() { System.out.println("Class class11"); } public void show(String s) { System.out.println("Class class11 : "+s); } } class Class12 extends Abs { public void show() { System.out.println("Class class12"); } } class Class2 extends Class1 { public void show() { System.out.println("Class Class2"); } public void show(String s) { System.out.println("Class Class2 : "+s); } } public class Polymorphism { public static void main(String ar[]) { Inter[] interobj={new Class1(), new Class2(), new Class11()}; Abs[] absobj={new Class1(),new Class2(), new Class12()}; Class1[] class1obj={new Class1(),new Class2()}; TopInter topinterobj=interobj[0]; for(int i=0;i<interobj.length;i++) { interobj[i].show(); //interobj[i].show("Polymorphism"); } for(int i=0;i<absobj.length;i++) { absobj[i].show(); absobj[i].show("Polymorphism"); } for(int i=0;i<class1obj.length;i++) { class1obj[i].show(); class1obj[i].show("Polymorphism"); } topinterobj.show(); } }
This code defines interfaces, a normal class, an abstract class, and a public class. The TopInter interface and the Abs abstract class are at the top of the inheritance hierarchy. The TopInter interface contains the show() method declaration. The Abs abstract class contains the show() method without a parameter and a nonabstract method, show(String s), with the string type parameter. The TopInter interface and the Abs abstract class are not related.
20
The Inter interface extends from the TopInter interface and does not have any members of its own. The Class1 class extends from the Abs abstract class and implements the interface Inter. This class provides body to the show() method. The show() method works for both the interface and the abstract class. This class also overrides the show(String s) method of an abstract class. The Class11 class implements the Inter interface and provides body to the show() method. This class also defines a method, show(String s), of its own. The Class12 class extends from the Abs abstract class and provides body to the show() abstract method of the parent class. The Class2 class extends from the Class1 class and overrides both the show() and show(String s) methods of the Class1 class. The main method in the public class creates three references of the Inter interface and assigns the objects of the Class1, Class2, and Class11 classes. The object of the Class12 class cannot be assigned in the interface reference Inter because it does not have any inheritance relation with the interface. The three references of the Abs abstract class type are created and the objects of classes Class1, Class2, and Class12 are assigned in them. The two objects of the Class1 class type are instantiated with the object of the Class1 and Class2 classes. A reference of the TopInter interface is assigned with a reference of type Inter, which actually points to the object of the Class1 class. The show() method is then called with the Inter interface reference. Different show methods are called, depending upon the object assigned to the interface reference. The object of the Inter interface cannot visualize the show(String s) method. The show() and show(String s) methods are called using the reference of the Abs abstract class and objects of the Class1 class. The TopInter interface reference calls the show() method. Note Java files can only contain one public class for each file. In addition, the name of the file and the public class in Java should not be identical.
22
Tip
Choose interfaces over abstract classes because interfaces do not bind the application with the restrictive inheritance hierarchy of Java. This makes the application easier to modify, except when you need to add or remove a method in the interface.
Related Topics
For related information on this topic, you can refer to: Understanding Classes and Objects in Java Multithreading in Java Using Collections in Java